source: soft/giet_vm/giet_kernel/sys_handler.c @ 645

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

Modify the task activation/desactivation mechanism
to support the _kill_application() and _exec_application() system functions.
The RUN Boolean in task context has been replaced by the NORUN bit-vector.

  • Property svn:executable set to *
File size: 71.0 KB
RevLine 
[258]1///////////////////////////////////////////////////////////////////////////////////
2// File     : sys_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner and joel porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <sys_handler.h>
9#include <tty_driver.h>
10#include <tim_driver.h>
11#include <nic_driver.h>
[440]12#include <mmc_driver.h>
[519]13#include <mwr_driver.h>
[440]14#include <cma_driver.h>
[258]15#include <ctx_handler.h>
16#include <fat32.h>
17#include <utils.h>
[478]18#include <kernel_malloc.h>
[459]19#include <tty0.h>
[396]20#include <vmem.h>
[322]21#include <hard_config.h>
[258]22#include <giet_config.h>
23#include <mapping_info.h>
[547]24#include <irq_handler.h>
[519]25#include <io.h>
[258]26
[322]27#if !defined(SEG_BOOT_MAPPING_BASE)
28# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
29#endif
30
[449]31#if !defined(NB_TTY_CHANNELS)
32# error: You must define NB_TTY_CHANNELS in the hard_config.h file
33#endif
34
[459]35#if (NB_TTY_CHANNELS < 1)
36# error: NB_TTY_CHANNELS cannot be smaller than 1!
37#endif
38
[449]39#if !defined(NB_TIM_CHANNELS)
40# error: You must define NB_TIM_CHANNELS in the hard_config.h file
41#endif
42
43#if !defined(NB_NIC_CHANNELS)
44# error: You must define NB_NIC_CHANNELS in the hard_config.h file
45#endif
46
47#if !defined(NB_CMA_CHANNELS)
48# error: You must define NB_CMA_CHANNELS in the hard_config.h file
49#endif
50
[478]51#if !defined(GIET_NO_HARD_CC)
52# error: You must define GIET_NO_HARD_CC in the giet_config.h file
[449]53#endif
54
[478]55#if !defined ( GIET_NIC_MAC4 )
56# error: You must define GIET_NIC_MAC4 in the giet_config.h file
[449]57#endif
58
[478]59#if !defined ( GIET_NIC_MAC2 )
60# error: You must define GIET_NIC_MAC2 in the giet_config.h file
[449]61#endif
62
[258]63////////////////////////////////////////////////////////////////////////////
[528]64//        Extern variables
[519]65////////////////////////////////////////////////////////////////////////////
66
[528]67// allocated in tty0.c file.
68extern sqt_lock_t _tty0_sqt_lock;
[519]69
[528]70// allocated in mwr_driver.c file.
71extern simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
[556]72extern unsigned int   _coproc_type[X_SIZE*Y_SIZE];
73extern unsigned int   _coproc_info[X_SIZE*Y_SIZE];
74extern unsigned int   _coproc_mode[X_SIZE*Y_SIZE];
75extern unsigned int   _coproc_error[X_SIZE*Y_SIZE];
76extern unsigned int   _coproc_gtid[X_SIZE*Y_SIZE];
[519]77
[556]78
[528]79// allocated in tty_driver.c file.
80extern unsigned int _tty_rx_full[NB_TTY_CHANNELS];
81extern unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
82
[629]83// allocated in kernel_init.c file
84extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
85
[519]86////////////////////////////////////////////////////////////////////////////
[440]87//     Channel allocators for peripherals
88//     (TTY[0] is reserved for kernel)
89////////////////////////////////////////////////////////////////////////////
90
[494]91__attribute__((section(".kdata")))
[478]92unsigned int _tty_channel_allocator    = 1;
[494]93
94__attribute__((section(".kdata")))
[478]95unsigned int _tim_channel_allocator    = 0;
[494]96
97__attribute__((section(".kdata")))
[478]98unsigned int _cma_channel_allocator    = 0;
[494]99
100__attribute__((section(".kdata")))
[449]101unsigned int _nic_rx_channel_allocator = 0;
[494]102
103__attribute__((section(".kdata")))
[449]104unsigned int _nic_tx_channel_allocator = 0;
[440]105
106////////////////////////////////////////////////////////////////////////////
[614]107//     NIC_RX and NIC_TX kernel chbuf arrays
[449]108////////////////////////////////////////////////////////////////////////////
109
[494]110__attribute__((section(".kdata")))
[614]111ker_chbuf_t  _nic_ker_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
[459]112
[494]113__attribute__((section(".kdata")))
[614]114ker_chbuf_t  _nic_ker_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
[459]115
[478]116////////////////////////////////////////////////////////////////////////////
117// FBF related chbuf descriptors array, indexed by the CMA channel index.
118// Physical addresses of these chbuf descriptors required for L2 cache sync.
[614]119// FBF status
[478]120////////////////////////////////////////////////////////////////////////////
[459]121
[494]122__attribute__((section(".kdata")))
[478]123fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
[459]124
[494]125__attribute__((section(".kdata")))
[478]126unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
127
[614]128__attribute__((section(".kdata")))
129buffer_status_t _fbf_status[NB_CMA_CHANNELS] __attribute__((aligned(64)));
130
[449]131////////////////////////////////////////////////////////////////////////////
[258]132//    Initialize the syscall vector with syscall handlers
133// Note: This array must be synchronised with the define in file stdio.h
134////////////////////////////////////////////////////////////////////////////
[494]135
136__attribute__((section(".kdata")))
[258]137const void * _syscall_vector[64] = 
138{
[556]139    &_sys_proc_xyp,                  /* 0x00 */
140    &_get_proctime,                  /* 0x01 */
141    &_sys_tty_write,                 /* 0x02 */
142    &_sys_tty_read,                  /* 0x03 */
143    &_sys_tty_alloc,                 /* 0x04 */
144    &_sys_tty_get_lock,              /* 0x05 */
145    &_sys_tty_release_lock,          /* 0x06 */
146    &_sys_heap_info,                 /* 0x07 */
147    &_sys_local_task_id,             /* 0x08 */
148    &_sys_global_task_id,            /* 0x09 */ 
149    &_sys_fbf_cma_alloc,             /* 0x0A */
[614]150    &_sys_fbf_cma_init_buf,          /* 0x0B */
151    &_sys_fbf_cma_start,             /* 0x0C */
152    &_sys_fbf_cma_display,           /* 0x0D */
153    &_sys_fbf_cma_stop,              /* 0x0E */
154    &_sys_task_exit,                 /* 0x0F */
[258]155
[614]156    &_sys_procs_number,              /* 0x10 */
157    &_sys_fbf_sync_write,            /* 0x11 */
158    &_sys_fbf_sync_read,             /* 0x12 */
159    &_sys_thread_id,                 /* 0x13 */
[556]160    &_sys_tim_alloc,                 /* 0x14 */
161    &_sys_tim_start,                 /* 0x15 */ 
162    &_sys_tim_stop,                  /* 0x16 */
[629]163    &_sys_kill_application,          /* 0x17 */
164    &_sys_exec_application,          /* 0x18 */   
[556]165    &_sys_context_switch,            /* 0x19 */
166    &_sys_vseg_get_vbase,            /* 0x1A */
167    &_sys_vseg_get_length,           /* 0x1B */
168    &_sys_xy_from_ptr,               /* 0x1C */
169    &_sys_ukn,                       /* 0x1D */
170    &_sys_ukn,                       /* 0x1E */
171    &_sys_ukn,                       /* 0x1F */
[258]172
[592]173    &_fat_open,                      /* 0x20 */
174    &_fat_read,                      /* 0x21 */
175    &_fat_write,                     /* 0x22 */
176    &_fat_lseek,                     /* 0x23 */
177    &_fat_file_info,                 /* 0x24 */
[556]178    &_fat_close,                     /* 0x25 */
[592]179    &_fat_remove,                    /* 0x26 */
180    &_fat_rename,                    /* 0x27 */
181    &_fat_mkdir,                     /* 0x28 */
182    &_fat_list,                      /* 0x29 */
[556]183    &_sys_ukn,                       /* 0x2A */
184    &_sys_ukn,                       /* 0x2B */
185    &_sys_ukn,                       /* 0x2C */
186    &_sys_ukn,                       /* 0x2D */
187    &_sys_ukn,                       /* 0x2E */
188    &_sys_ukn,                       /* 0x2F */
[258]189
[556]190    &_sys_nic_alloc,                 /* 0x30 */
191    &_sys_nic_start,                 /* 0x31 */
192    &_sys_nic_move,                  /* 0x32 */
193    &_sys_nic_stop,                  /* 0x33 */
194    &_sys_nic_stats,                 /* 0x34 */
195    &_sys_nic_clear,                 /* 0x35 */ 
196    &_sys_ukn,                       /* 0x36 */
197    &_sys_ukn,                       /* 0x37 */
198    &_sys_ukn,                       /* 0x38 */   
199    &_sys_ukn,                       /* 0x39 */
200    &_sys_ukn,                       /* 0x3A */
201    &_sys_coproc_completed,          /* 0x3B */
202    &_sys_coproc_alloc,              /* 0x3C */
203    &_sys_coproc_channel_init,       /* 0x3D */
204    &_sys_coproc_run,                /* 0x3E */
205    &_sys_coproc_release,            /* 0x3F */
[258]206};
207
[459]208
[258]209//////////////////////////////////////////////////////////////////////////////
[519]210//           Coprocessors related syscall handlers
211//////////////////////////////////////////////////////////////////////////////
212
213//////////////////////////////////////////////////
214int _sys_coproc_alloc( unsigned int   coproc_type,
[556]215                       unsigned int*  coproc_info )
[519]216{
217    // In this implementation, the allocation policy is constrained:
218    // the coprocessor must be in the same cluster as the calling task,
[556]219    // and there is at most one coprocessor per cluster
[519]220
221    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
222    mapping_cluster_t * cluster = _get_cluster_base(header);
223    mapping_periph_t  * periph  = _get_periph_base(header);
224
225    // get cluster coordinates and cluster global index
226    unsigned int procid     = _get_procid();
227    unsigned int x          = procid >> (Y_WIDTH + P_WIDTH);
228    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]229    unsigned int cluster_id = x * Y_SIZE + y;
[519]230 
231    // search coprocessor in cluster
232    mapping_periph_t*  found = NULL;
233    unsigned int min   = cluster[cluster_id].periph_offset;
234    unsigned int max   = min + cluster[cluster_id].periphs;
235    unsigned int periph_id;
236    for ( periph_id = min ; periph_id < max ; periph_id++ )
237    {
238        if ( (periph[periph_id].type == PERIPH_TYPE_MWR) &&
239             (periph[periph_id].subtype == coproc_type) )
240        {
241            found = &periph[periph_id];
242            break;
243        }
244    } 
245
246    if ( found != NULL )
247    {
248        // get the lock (at most one coproc per cluster)
249        _simple_lock_acquire( &_coproc_lock[cluster_id] );
[556]250
251        // register coproc characteristics in kernel arrays
252        _coproc_type[cluster_id] = coproc_type;
253        _coproc_info[cluster_id] = (found->arg0 & 0xFF)     |
254                                   (found->arg1 & 0xFF)<<8  |
255                                   (found->arg2 & 0xFF)<<16 |
256                                   (found->arg3 & 0xFF)<<24 ;
257
[519]258        // returns coprocessor info
[556]259        *coproc_info = _coproc_info[cluster_id];
[519]260
[556]261        // register coprocessor coordinates in task context
262        unsigned int cluster_xy = (x<<Y_WIDTH) + y;
263        _set_context_slot( CTX_COPROC_ID , cluster_xy );
264
[519]265#if GIET_DEBUG_COPROC
266_printf("\n[GIET DEBUG COPROC] _sys_coproc_alloc() in cluster[%d,%d]\n"
267        "  coproc_info = %x / cluster_xy = %x\n",
[556]268        x , y , *coproc_info , cluster_xy );
[519]269#endif
270        return 0;
271    }
272    else
273    {
274         _printf("\n[GIET_ERROR] in _sys_coproc_alloc(): no coprocessor "
275                 " with type %d available in cluster[%d,%d]\n",
276                 coproc_type , x , y );
277        return -1;
278    }
279}  // end _sys_coproc_alloc()
280
[556]281////////////////////////////////////////////////////////
282int _sys_coproc_release( unsigned int coproc_reg_index )
[519]283{
[556]284    // processor coordinates
[519]285    unsigned int procid = _get_procid();
286    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
287    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]288    unsigned int p      = procid & ((1<<P_WIDTH)-1);
289   
290    // get coprocessor coordinates
291    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
292    if ( cluster_xy > 0xFF )
[519]293    {
[556]294         _printf("\n[GIET_ERROR] in _sys_coproc_release(): "
295                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
296                 x , y , p ); 
[519]297         return -1;
298    }
299
[556]300    unsigned int cx         = cluster_xy >> Y_WIDTH;
301    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
302    unsigned int cluster_id = cx * Y_SIZE + cy;
303    unsigned int info       = _coproc_info[cluster_id];
304    unsigned int nb_to      = info & 0xFF;
305    unsigned int nb_from    = (info>>8) & 0xFF;
306    unsigned int channel;
[519]307
[556]308    // stops coprocessor and communication channels
309    _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 0 );
310    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
311    {
312        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 );
313    }
[519]314
[556]315    // deallocates coprocessor coordinates in task context
316    _set_context_slot( CTX_COPROC_ID , 0xFFFFFFFF );
317
318    // release coprocessor lock
319    _simple_lock_release( &_coproc_lock[cluster_id] );
320
[519]321#if GIET_DEBUG_COPROC
322_printf("\n[GIET DEBUG COPROC] _sys_coproc_release() in cluster[%d,%d]\n",
[556]323        cx, cy );
[519]324#endif
325
326    return 0;
327}  // end _sys_coproc_release()
328
[556]329//////////////////////////////////////////////////////////////
330int _sys_coproc_channel_init( unsigned int            channel,
[519]331                              giet_coproc_channel_t*  desc )
332{
[556]333    // processor coordinates
[519]334    unsigned int procid = _get_procid();
335    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
336    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]337    unsigned int p      = procid & ((1<<P_WIDTH)-1);
338   
339    // get coprocessor coordinates
340    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
341    if ( cluster_xy > 0xFF )
[519]342    {
343         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
[556]344                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
345                 x , y , p ); 
[519]346         return -1;
347    }
348
349    // check channel mode
350    unsigned mode = desc->channel_mode;
351    if ( (mode != MODE_MWMR) && 
352         (mode != MODE_DMA_IRQ) && 
353         (mode != MODE_DMA_NO_IRQ) )
354    {
[556]355         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
[519]356                 " illegal mode\n");
357         return -1;
358    }
359
360    // get memory buffer size
361    unsigned int size = desc->buffer_size;
362 
[528]363    // physical addresses
[519]364    unsigned long long buffer_paddr;
365    unsigned int       buffer_lsb;
366    unsigned int       buffer_msb;
[556]367    unsigned long long mwmr_paddr = 0;
[519]368    unsigned int       mwmr_lsb;
369    unsigned int       mwmr_msb;
[556]370    unsigned long long lock_paddr = 0;
[519]371    unsigned int       lock_lsb;
372    unsigned int       lock_msb;
373
[528]374    unsigned int       flags;     // unused
375
[519]376    // compute memory buffer physical address
[528]377    buffer_paddr = _v2p_translate( desc->buffer_vaddr , &flags );
378    buffer_lsb   = (unsigned int)buffer_paddr;
379    buffer_msb   = (unsigned int)(buffer_paddr>>32); 
[519]380
381    // call MWMR_DMA driver
[556]382    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MODE, mode ); 
383    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_SIZE, size ); 
384    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_LSB, buffer_lsb ); 
385    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_MSB, buffer_msb ); 
[519]386                       
387    if ( mode == MODE_MWMR )
388    {
[528]389        // compute MWMR descriptor physical address
390        mwmr_paddr = _v2p_translate( desc->mwmr_vaddr , &flags );
[519]391        mwmr_lsb = (unsigned int)mwmr_paddr;
392        mwmr_msb = (unsigned int)(mwmr_paddr>>32); 
393
[528]394        // call MWMR_DMA driver
[556]395        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_LSB, mwmr_lsb ); 
396        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_MSB, mwmr_msb ); 
[528]397
398        // compute lock physical address
399        lock_paddr = _v2p_translate( desc->lock_vaddr , &flags );
[519]400        lock_lsb = (unsigned int)lock_paddr;
401        lock_msb = (unsigned int)(lock_paddr>>32); 
402
403        // call MWMR_DMA driver
[556]404        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_LSB, lock_lsb ); 
405        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_MSB, lock_msb ); 
[519]406    }
407
408#if GIET_DEBUG_COPROC
[556]409_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_init() for coproc[%d,%d]\n"
[519]410        " channel =  %d / mode = %d / buffer_size = %d\n"
411        " buffer_paddr = %l / mwmr_paddr = %l / lock_paddr = %l\n",
412        x , y , channel , mode , size ,
413        buffer_paddr, mwmr_paddr, lock_paddr );
414#endif
415       
416    return 0;
417} // end _sys_coproc_channel_init()
418
[556]419////////////////////////////////////////////////////
420int _sys_coproc_run( unsigned int coproc_reg_index )
[519]421{
[556]422    // processor coordinates
[519]423    unsigned int procid = _get_procid();
424    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
425    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]426    unsigned int p      = procid & ((1<<P_WIDTH)-1);
427   
428    // get coprocessor coordinates
429    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
430    if ( cluster_xy > 0xFF )
[519]431    {
[556]432         _printf("\n[GIET_ERROR] in _sys_coproc_run(): "
433                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
434                 x , y , p ); 
[519]435         return -1;
436    }
437
[556]438    unsigned int cx         = cluster_xy >> Y_WIDTH;
439    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
440    unsigned int cluster_id = cx * Y_SIZE + cy;
441    unsigned int info       = _coproc_info[cluster_id];
442    unsigned int nb_to      = info & 0xFF;
443    unsigned int nb_from    = (info>>8) & 0xFF;
444    unsigned int mode       = 0xFFFFFFFF;
445    unsigned int channel;
[519]446
[556]447    // register coprocessor running mode
448    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
449    {
450        unsigned int temp;
451        temp = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_MODE );
[519]452
[556]453        if ( mode == 0xFFFFFFFF ) 
454        {
455            mode = temp;
456        }
457        else if ( temp != mode )
458        {
459            _printf("\n[GIET_ERROR] P[%d,%d,%d] in _sys_coproc_run() for coprocessor[%d,%d]\n"
460                    "  all channels don't have the same mode\n", x , y , p , cx , cy );
461            return -1;
462        }
463    }
464    _coproc_mode[cluster_id] = mode;
[519]465
[556]466    // start all communication channels
467    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
468    {
469        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 1 );
470    }
[519]471
[556]472    //////////////////////////////////////////////////////////////////////////
473    if ( (mode == MODE_MWMR) || (mode == MODE_DMA_NO_IRQ) )  // no descheduling
[519]474    {
[556]475        // start coprocessor
476        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
477
478#if GIET_DEBUG_COPROC
479if ( mode == MODE_MWMR )
480_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
481        "   MODE_MWMR at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
482else
483_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
484        "   MODE_DMA_NO_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
485#endif
486
487        return 0;
[519]488    }
[556]489    ///////////////////////////////////////////////////////////////////////////
490    else                                // mode == MODE_DMA_IRQ => descheduling
491    {
492        // set _coproc_gtid
493        unsigned int ltid = _get_current_task_id();
494        _coproc_gtid[cluster_id] = (procid<<16) + ltid;
[519]495
[556]496        // enters critical section
497        unsigned int save_sr;
498        _it_disable( &save_sr ); 
499
[629]500        // set NORUN_MASK_COPROC bit
501        static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
502        unsigned int*       ptr     = &psched->context[ltid][CTX_NORUN_ID];
503        _atomic_or( ptr , NORUN_MASK_COPROC );
[556]504
505        // start coprocessor
506        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
507
[519]508#if GIET_DEBUG_COPROC
[556]509_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
510        "   MODE_DMA_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
[519]511#endif
512
[556]513        // deschedule task
514        _ctx_switch(); 
[519]515
[556]516#if GIET_DEBUG_COPROC
517_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] resume\n"
518        "  coprocessor[%d,%d] completion at cycle %d\n", 
519        x , y , p , cx , cy , _get_proctime() );
520#endif
521
522        // restore SR
523        _it_restore( &save_sr );
524
525        // return error computed by mwr_isr()
526        return _coproc_error[cluster_id];
527    } 
528} // end _sys_coproc_run()
529
530///////////////////////////
531int _sys_coproc_completed()
[519]532{
[556]533    // processor coordinates
[519]534    unsigned int procid = _get_procid();
535    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
536    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
[556]537    unsigned int p      = procid & ((1<<P_WIDTH)-1);
538   
539    // get coprocessor coordinates
540    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
541    if ( cluster_xy > 0xFF )
[519]542    {
543         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
[556]544                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
545                 x , y , p ); 
[519]546         return -1;
547    }
548
[556]549    unsigned int cx         = cluster_xy >> Y_WIDTH;
550    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
551    unsigned int cluster_id = cx * Y_SIZE + cy;
552    unsigned int mode       = _coproc_mode[cluster_id];
[519]553
[556]554    // analyse possible errors
555    if ( mode == MODE_DMA_NO_IRQ )
556    {
557        unsigned int info       = _coproc_info[cluster_id];
558        unsigned int nb_to      = info & 0xFF;
559        unsigned int nb_from    = (info>>8) & 0xFF;
560        unsigned int error      = 0;
561        unsigned int channel;
562        unsigned int status;
563
564        // get status for all channels, and signal all reported errors
565        for ( channel = 0 ; channel < (nb_to +nb_from) ; channel++ )
566        {
567            do
568            {
569                status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
570                if ( status == MWR_CHANNEL_ERROR_DATA )
571                {
572                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
573                            " / channel %d / DATA_ERROR\n", channel );
574                    error = 1;
575                    break;
576                }
577                else if ( status == MWR_CHANNEL_ERROR_LOCK )
578                {
579                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
580                            " / channel %d / LOCK_ERROR\n", channel );
581                    error = 1;
582                    break;
583                }
584                else if ( status == MWR_CHANNEL_ERROR_DESC )
585                {
586                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
587                            " / channel %d / DESC_ERROR\n", channel );
588                    error = 1;
589                    break;
590                }
591            } while ( status == MWR_CHANNEL_BUSY );
592
593            // reset channel
594            _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 ); 
595
596        }  // end for channels
597
[519]598#if GIET_DEBUG_COPROC
[556]599_printf("\n[GIET DEBUG COPROC] _sys_coproc_completed() for coprocessor[%d,%d] error = %d\n", 
600        cx , cy , error );
[519]601#endif
602
[556]603        return error;
604    }
605    else  // mode == MODE_MWMR or MODE_DMA_IRQ
606    {
607        _printf("\n[GIET ERROR] sys_coproc_completed() should not be called for "
608                "coprocessor[%d,%d] running in MODE_MWMR or MODE_DMA_IRQ\n", cx , cy );
609        return 1;
610    }
[519]611} // end _sys_coproc_completed()
612
613
614//////////////////////////////////////////////////////////////////////////////
[440]615//             TTY related syscall handlers
[258]616//////////////////////////////////////////////////////////////////////////////
[440]617
618////////////////////
619int _sys_tty_alloc()
[258]620{
[440]621    // get a new TTY terminal index
[459]622    unsigned int channel = _atomic_increment( &_tty_channel_allocator, 1 );
[440]623
624    if ( channel >= NB_TTY_CHANNELS )
625    {
626        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n");
627        return -1;
628    }
629    else
630    {
631    }
[547]632
633    // allocate a WTI mailbox to the calling proc if external IRQ
634    unsigned int unused;
635    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &unused ); 
636   
637    // update calling task index
638    _set_context_slot( CTX_TTY_ID, channel );
639
640    return 0;
[258]641}
642
[440]643/////////////////////////////////////////////////
644int _sys_tty_write( const char*  buffer,   
645                    unsigned int length,    // number of characters
646                    unsigned int channel)   // channel index
647{
648    unsigned int  nwritten;
649
650    // compute and check tty channel
651    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
652    if( channel >= NB_TTY_CHANNELS ) return -1;
653
654    // write string to TTY channel
655    for (nwritten = 0; nwritten < length; nwritten++) 
656    {
657        // check tty's status
658        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
659
660        // write one byte
661        if (buffer[nwritten] == '\n') 
662        {
663            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
664        }
665        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
666    }
667   
668    return nwritten;
669}
670
671////////////////////////////////////////////////
672int _sys_tty_read( char*        buffer, 
673                   unsigned int length,    // unused
674                   unsigned int channel)   // channel index
675{
676    // compute and check tty channel
677    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
678    if( channel >= NB_TTY_CHANNELS ) return -1;
679
680    // read one character from TTY channel
681    if (_tty_rx_full[channel] == 0) 
682    {
683        return 0;
684    }
685    else 
686    {
687        *buffer = _tty_rx_buf[channel];
688        _tty_rx_full[channel] = 0;
689        return 1;
690    }
691}
692
693///////////////////////////////////////////
[494]694int _sys_tty_get_lock( unsigned int   channel,       // unused
[440]695                       unsigned int * save_sr_ptr )
696{
[494]697    // check tty channel
698    if( channel != 0 )  return 1;
[440]699
700    _it_disable( save_sr_ptr );
[494]701    _sqt_lock_acquire( &_tty0_sqt_lock );
[440]702    return 0;
703}
704
705///////////////////////////////////////////////
706int _sys_tty_release_lock( unsigned int   channel,
707                           unsigned int * save_sr_ptr )
708{
[494]709    // check tty channel
710    if( channel != 0 )  return 1;
[440]711
[494]712    _sqt_lock_release( &_tty0_sqt_lock );
[440]713    _it_restore( save_sr_ptr );
714    return 0;
715}
716
[428]717//////////////////////////////////////////////////////////////////////////////
[440]718//             TIM related syscall handlers
[428]719//////////////////////////////////////////////////////////////////////////////
[440]720
721////////////////////
722int _sys_tim_alloc()
[428]723{
[440]724    // get a new timer index
[459]725    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
[440]726
727    if ( channel >= NB_TIM_CHANNELS )
728    {
729        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
730        return -1;
731    }
732    else
733    {
[449]734        _set_context_slot( CTX_TIM_ID, channel );
735        return 0;
[440]736    }
737}
738
739/////////////////////////////////////////
740int _sys_tim_start( unsigned int period )
741{
742    // get timer index
743    unsigned int channel = _get_context_slot( CTX_TIM_ID );
744    if ( channel >= NB_TIM_CHANNELS )
745    {
746        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
747        return -1;
748    }
749
750    // start timer
751    _timer_start( channel, period );
752
753    return 0;
754}
755
756///////////////////
757int _sys_tim_stop()
758{
759    // get timer index
760    unsigned int channel = _get_context_slot( CTX_TIM_ID );
761    if ( channel >= NB_TIM_CHANNELS )
762    {
763        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
764        return -1;
765    }
766
767    // stop timer
768    _timer_stop( channel );
769
770    return 0;
771}
772
773//////////////////////////////////////////////////////////////////////////////
774//             NIC related syscall handlers
775//////////////////////////////////////////////////////////////////////////////
776
[478]777#define NIC_CONTAINER_SIZE 4096
778
[494]779////////////////////////////////////////
780int _sys_nic_alloc( unsigned int is_rx,
781                    unsigned int xmax,
782                    unsigned int ymax )
[440]783{
[494]784    // check xmax / ymax parameters
785    if ( xmax > X_SIZE )
786    {
787        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
788        return -1;
789    }
790    if ( ymax > Y_SIZE )
791    {
792        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
793        return -1;
794    }
[459]795
[614]796    ////////////////////////////////////////////////////////
797    // Step 1: get and register CMA and NIC channel index //
798    ////////////////////////////////////////////////////////
799
[494]800    // get a NIC_RX or NIC_TX channel index
[449]801    unsigned int nic_channel;
802    unsigned int cma_channel;
[440]803
[459]804    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
805    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
[449]806
807    if ( (nic_channel >= NB_NIC_CHANNELS) )
[440]808    {
[449]809        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
[440]810        return -1;
811    }
[449]812
813    // get a CMA channel index
[459]814    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
[449]815
816    if ( cma_channel >= NB_CMA_CHANNELS )
817    {
818        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
819        return -1;
820    }
[459]821
[494]822#if GIET_DEBUG_NIC
823unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
824_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
[547]825        "  nic_channel = %d / cma_channel = %d\n",
[494]826        thread , _get_proctime() , nic_channel , cma_channel );
827#endif
828
[449]829    // register nic_index and cma_index in task context
830    if ( is_rx )
831    {
832        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
833        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
834    }
[440]835    else
836    {
[449]837        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
838        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
[440]839    }
840
[614]841    /////////////////////////////////////////////////////////////////////////////////
842    // Step 2: loop on all the clusters                                            //
843    // Allocate the kernel containers and status, compute the container and the    //
844    // status physical addresses, fill and synchronize the kernel CHBUF descriptor //
845    /////////////////////////////////////////////////////////////////////////////////
846
[494]847    // physical addresses to be registered in the CMA registers
[459]848    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
849    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
[449]850
[614]851    // allocate one kernel container and one status variable per cluster in the
852    // (xmax / ymax) mesh
[528]853    unsigned int        cx;                 // cluster X coordinate
854    unsigned int        cy;                 // cluster Y coordinate
855    unsigned int        index;              // container index in chbuf
856    unsigned int        vaddr;              // virtual address
857    unsigned long long  cont_paddr;         // container physical address
[614]858    unsigned long long  sts_paddr;          // container status physical address
[494]859
[528]860    unsigned int        flags;              // for _v2p_translate()
861
[494]862    for ( cx = 0 ; cx < xmax ; cx++ )
[478]863    {
[494]864        for ( cy = 0 ; cy < ymax ; cy++ )
[478]865        {
866            // compute index in chbuf
[494]867            index = (cx * ymax) + cy; 
[478]868
[494]869            // allocate the kernel container
[478]870            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
871
[494]872            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
873            {
874                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
875                        " in cluster[%d,%d]\n", cx, cy );
876                return -1;
877            }
878
[478]879            // compute container physical address
[528]880            cont_paddr = _v2p_translate( vaddr , &flags );
[478]881
[614]882            // checking container address alignment
883            if ( cont_paddr & 0x3F )
884            {
885                _printf("\n[GIET ERROR] in _sys_nic_alloc() : container address of cluster[%d,%d] not aligned\n",
886                        cx, cy);
887                return -1;
888            }
889
890#if GIET_DEBUG_NIC
891_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
892        " allocates in cluster[%d,%d]:\n"
893        " - container vaddr = %x / paddr = %l\n",
894        thread , cx , cy , vaddr, cont_paddr );
895#endif
896
897            // allocate the kernel container status
898            // it occupies 64 bytes but only last bit is useful (1 for full and 0 for empty)
899            vaddr = (unsigned int)_remote_malloc( 64, cx, cy );
900
901            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
902            {
903                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
904                        " in cluster[%d,%d]\n", cx, cy );
905                return -1;
906            }
907
908            // compute status physical address
909            sts_paddr = _v2p_translate( vaddr , &flags );
910
911            // checking status address alignment
912            if ( sts_paddr & 0x3F )
913            {
914                _printf("\n[GIET ERROR] in _sys_nic_alloc() : status address of cluster[%d,%d] not aligned\n",
915                        cx, cy);
916                return -1;
917            }
918
[494]919            // initialize chbuf entry
[614]920            // The buffer descriptor has the following structure:
921            // - the 26 LSB bits contain bits[6:31] of the buffer physical address
922            // - the 26 following bits contain bits[6:31] of the physical address where the
923            //   buffer status is located
924            // - the 12 MSB bits contain the common address extension of the buffer and its
925            //   status
926            if ( is_rx )
927                _nic_ker_rx_chbuf[nic_channel].buf_desc[index] =
928                    (unsigned long long)
929                    ((sts_paddr & 0xFFFFFFFFULL) >> 6) +
930                    (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26);
931            else
932                _nic_ker_tx_chbuf[nic_channel].buf_desc[index] =
933                    (unsigned long long)
934                    ((sts_paddr & 0xFFFFFFC0ULL) >> 6) +
935                    (((cont_paddr & 0xFFFFFFFFFC0ULL) >> 6) << 26);
[478]936
937#if GIET_DEBUG_NIC
[614]938_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
939        " - status vaddr = %x / paddr = %l\n"
940        " Buffer descriptor = %l\n",
941        thread, vaddr, sts_paddr,
942        (unsigned long long)((sts_paddr & 0xFFFFFFFFULL) >> 6) + 
943        (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26) );
[478]944#endif
945        }
946    }
947
[494]948    // complete kernel chbuf initialisation
949    if ( is_rx )
950    {
[614]951        _nic_ker_rx_chbuf[nic_channel].xmax = xmax;
952        _nic_ker_rx_chbuf[nic_channel].ymax = ymax;
[494]953    }
954    else
955    {
[614]956        _nic_ker_tx_chbuf[nic_channel].xmax = xmax;
957        _nic_ker_tx_chbuf[nic_channel].ymax = ymax;
[494]958    }
959
[449]960    // compute the kernel chbuf descriptor physical address
[614]961    if ( is_rx ) vaddr = (unsigned int)( &_nic_ker_rx_chbuf[nic_channel] );
962    else         vaddr = (unsigned int)( &_nic_ker_tx_chbuf[nic_channel] );
[440]963
[528]964    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
965
[459]966#if GIET_DEBUG_NIC
[547]967_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
968        "  vaddr = %x / paddr = %l\n",
[478]969        thread , vaddr , ker_chbuf_pbase );
[459]970#endif
[440]971
[459]972    // sync the kernel chbuf in L2 after write in L2
[614]973    _mmc_sync( ker_chbuf_pbase, sizeof( ker_chbuf_t ) );
[459]974
[614]975    ///////////////////////////////////////////////////////////////
976    // Step 3: compute the NIC chbuf descriptor physical address //
977    ///////////////////////////////////////////////////////////////
978
979    unsigned int offset;
980    if ( is_rx ) offset = 0x4100;
981    else         offset = 0x4110;
982    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
983                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
984
985#if GIET_DEBUG_NIC
986_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
987        thread , nic_chbuf_pbase );
988#endif
989
990    ////////////////////////////////////////////////////////////////////////////////
991    // Step 4: initialize CMA registers defining the source & destination chbufs //
992    ////////////////////////////////////////////////////////////////////////////////
993
[459]994    if ( is_rx )               // NIC to kernel
995    {
996        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
997        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
998        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
999        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
1000        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
[494]1001        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
[459]1002    }
1003    else                      // kernel to NIC
1004    {
1005        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
1006        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
[494]1007        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
[459]1008        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
1009        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
1010        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
1011    }
1012
[494]1013#if GIET_DEBUG_NIC
1014_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
1015        thread, _get_proctime() );
1016#endif
1017
1018    return nic_channel;
1019} // end _sys_nic_alloc()
1020
1021
1022////////////////////////////////////////
1023int _sys_nic_start( unsigned int is_rx,
1024                    unsigned int channel )
1025{
1026    unsigned int nic_channel;
1027    unsigned int cma_channel;
1028
1029    // get NIC channel index and CMA channel index from task context
1030    if ( is_rx )
1031    {
1032        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1033        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
1034    }
1035    else
1036    {
1037        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1038        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1039    }
1040
1041#if GIET_DEBUG_NIC
1042unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
[547]1043_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d\n"
1044        "  get NIC channel = %d / CMA channel = %d\n",
[494]1045        thread, _get_proctime(), nic_channel, cma_channel );
1046#endif
1047
1048    // check NIC and CMA channels index
1049    if ( nic_channel != channel )
1050    {
1051        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
1052        return -1;
1053    }
1054    if ( cma_channel >= NB_CMA_CHANNELS )
1055    {
1056        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
1057        return -1;
1058    }
1059
[449]1060    // start CMA transfer
[478]1061    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
[505]1062    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
[449]1063    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
1064
1065    // activates NIC channel
[614]1066    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 );
[459]1067
1068#if GIET_DEBUG_NIC
[614]1069    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
1070            thread , _get_proctime() );
[459]1071#endif
1072
[449]1073    return 0;
[505]1074}  // end _sys_nic_start()
[449]1075
[494]1076
[449]1077//////////////////////////////////////
1078int _sys_nic_move( unsigned int is_rx,
[459]1079                   unsigned int channel,
[449]1080                   void*        buffer )
1081{
1082
[459]1083#if GIET_DEBUG_NIC
1084unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
[478]1085_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
1086        thread , _get_proctime() );
[459]1087#endif
1088
[494]1089    // check NIC channel index
1090    if ( channel >= NB_NIC_CHANNELS )
1091    {
1092        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
1093        return -1;
1094    }
1095
1096    // get kernel chbuf virtual address
[614]1097    ker_chbuf_t* ker_chbuf;
1098    if ( is_rx )  ker_chbuf = &_nic_ker_rx_chbuf[channel];
1099    else          ker_chbuf = &_nic_ker_tx_chbuf[channel];
[494]1100
1101    // get xmax / ymax parameters
[614]1102    unsigned int xmax = ker_chbuf->xmax;
1103    unsigned int ymax = ker_chbuf->ymax;
[494]1104
[478]1105    // get cluster coordinates for the processor running the calling task
1106    unsigned int  procid = _get_procid();
1107    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
1108    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1109   
[494]1110    // check processor coordinates / (xmax,ymax)
1111    if ( cx >= xmax )
1112    {
1113        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
1114                " / xmax = %d\n", cx , xmax );
1115        return -1;
1116    }
1117    if ( cy >= ymax )
1118    {
1119        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
1120                " / ymax = %d\n", cy , ymax );
1121        return -1;
1122    }
1123   
[614]1124    unsigned long long usr_buf_paddr;       // user buffer physical address
1125    unsigned long long ker_buf_paddr;       // kernel buffer physical address
1126    unsigned long long ker_sts_paddr;       // kernel buffer status physical address
1127    unsigned long long ker_buf_desc;        // kernel buffer descriptor
1128    unsigned int       ker_sts;             // kernel buffer status (full or empty)
1129    unsigned int       index;               // kernel buffer index in chbuf
1130    unsigned int       flags;               // for _v2P_translate
[459]1131
1132    // Compute user buffer physical address and check access rights
[614]1133    usr_buf_paddr = _v2p_translate( (unsigned int)buffer , &flags );
[478]1134
[440]1135    if ( (flags & PTE_U) == 0 )
1136    {
[614]1137        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
[440]1138        return -1;
1139    }
1140
[459]1141#if GIET_DEBUG_NIC
[478]1142_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
[614]1143        thread, usr_buf_paddr );
[459]1144#endif
[440]1145
[614]1146    // compute buffer index, buffer descriptor paddr and buffer status paddr
1147    index = (ymax * cx) + cy;
1148    ker_buf_desc = ker_chbuf->buf_desc[index];
1149    ker_sts_paddr = ((ker_buf_desc & 0xFFF0000000000000ULL) >> 20) +
1150                    ((ker_buf_desc & 0x3FFFFFFULL) << 6);
[459]1151
[614]1152#if GIET_DEBUG_NIC
1153_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_desc %d at cycle %d\n"
1154        "  kernel buffer descriptor = %l\n",
1155        thread, index, _get_proctime(), ker_buf_desc );
1156#endif
1157
[494]1158    // poll local kernel container status until success
[478]1159    while ( 1 )
[449]1160    {
[478]1161        // inval buffer descriptor in L2 before read in L2
[614]1162        _mmc_inval( ker_sts_paddr, 4 );
1163        ker_sts = _physical_read( ker_sts_paddr );
[459]1164
1165#if GIET_DEBUG_NIC
[614]1166_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_sts %d at cycle %d\n"
1167        "  paddr = %l / kernel buffer status = %x\n",
1168        thread, index, _get_proctime(), ker_sts_paddr, ker_sts );
[459]1169#endif
1170
[478]1171        // test buffer status and break if found
[614]1172        if ( ( is_rx != 0 ) && ( ker_sts == 0x1 ) ) break;
1173        if ( ( is_rx == 0 ) && ( ker_sts == 0 ) ) break;
[449]1174    }
[459]1175
1176    // compute kernel buffer physical address
[614]1177    ker_buf_paddr = (ker_buf_desc & 0xFFFFFFFFFC000000ULL) >> 20;
[449]1178   
[494]1179    // move one container
1180    if ( is_rx )              // RX transfer
[459]1181    {
1182        // inval kernel buffer in L2 before read in L2
[614]1183        _mmc_inval( ker_buf_paddr, NIC_CONTAINER_SIZE );
[449]1184
[459]1185        // transfer data from kernel buffer to user buffer
[614]1186        _physical_memcpy( usr_buf_paddr, 
1187                          ker_buf_paddr, 
[478]1188                          NIC_CONTAINER_SIZE );
1189#if GIET_DEBUG_NIC
[547]1190_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
1191        " to user buffer %l at cycle %d\n",
[614]1192        thread , ker_buf_paddr , usr_buf_paddr , _get_proctime() );
[478]1193#endif
[449]1194
[459]1195    }
[494]1196    else                      // TX transfer
[459]1197    {
1198        // transfer data from user buffer to kernel buffer
[614]1199        _physical_memcpy( ker_buf_paddr, 
1200                          usr_buf_paddr, 
[478]1201                          NIC_CONTAINER_SIZE );
[449]1202
[459]1203        // sync kernel buffer in L2 after write in L2
[614]1204        _mmc_sync( ker_buf_paddr, NIC_CONTAINER_SIZE );
[478]1205
1206#if GIET_DEBUG_NIC
1207_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
1208        "user buffer %l to kernel buffer %l at cycle %d\n",
[614]1209        thread , usr_buf_paddr , ker_buf_paddr , _get_proctime() );
[478]1210#endif
1211
[459]1212    }
1213
[478]1214    // update kernel chbuf status
[614]1215    if ( is_rx ) _physical_write ( ker_sts_paddr, 0 );
1216    else         _physical_write ( ker_sts_paddr, 0x1 );
[459]1217
1218    // sync kernel chbuf in L2 after write in L2
[614]1219    _mmc_sync( ker_sts_paddr, 4 );
[459]1220
1221#if GIET_DEBUG_NIC
[478]1222_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
1223        thread , index , _get_proctime() );
[459]1224#endif
1225
[440]1226    return 0;
[449]1227} // end _sys_nic_move()
[440]1228
[494]1229
[449]1230////////////////////////////////////////
[489]1231int _sys_nic_stop( unsigned int is_rx,
1232                   unsigned int channel )
[440]1233{
[449]1234    unsigned int nic_channel;
1235    unsigned int cma_channel;
[440]1236
[449]1237    // get NIC channel index and CMA channel index
1238    if ( is_rx )
[440]1239    {
[449]1240        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1241        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
[440]1242    }
[449]1243    else
1244    {
1245        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1246        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1247    }
[440]1248
[494]1249    // check NIC and CMA channels index
[489]1250    if ( nic_channel != channel )
[440]1251    {
[494]1252        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
[440]1253        return -1;
1254    }
[449]1255    if ( cma_channel >= NB_CMA_CHANNELS )
[440]1256    {
[489]1257        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
[440]1258        return -1;
1259    }
1260
[449]1261    // desactivates the NIC channel
1262    _nic_channel_stop( nic_channel, is_rx );
[440]1263
[449]1264    // desactivates the CMA channel
[505]1265    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
[449]1266
[440]1267    return 0;
[494]1268}  // end _sys_nic_stop()
[440]1269
[459]1270////////////////////////////////////////
[489]1271int _sys_nic_clear( unsigned int is_rx,
1272                    unsigned int channel )
[459]1273{
1274    unsigned int nic_channel;
1275
1276    // get NIC channel
1277    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1278    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1279
[489]1280    if ( nic_channel != channel )
[459]1281    {
[489]1282        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
[459]1283        return -1;
1284    }
1285
1286    if ( is_rx )
1287    {
1288        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
1289        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
1290        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
1291        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
1292        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
1293        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
1294        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
1295        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
1296        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
1297    } 
1298    else
1299    {
1300        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
1301        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
1302        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
1303        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
1304        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
1305        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
1306        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
1307    }
1308    return 0;
[494]1309}  // en _sys_nic_clear()
[459]1310
1311////////////////////////////////////////
[489]1312int _sys_nic_stats( unsigned int is_rx,
1313                    unsigned int channel )
[459]1314{
1315    unsigned int nic_channel;
1316
1317    // get NIC channel
1318    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1319    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1320
[489]1321    if ( nic_channel != channel )
[459]1322    {
[489]1323        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
[459]1324        return -1;
1325    }
1326
1327    if ( is_rx )
1328    {
1329        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
1330        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
1331        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
1332        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
1333        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
1334        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
1335        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
1336        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
1337
1338        _printf("\n### Network Controller RX Statistics ###\n"
1339                "- packets received : %d\n"
1340                "- too small        : %d\n"
1341                "- too big          : %d\n"
1342                "- fifo full        : %d\n" 
1343                "- crc fail         : %d\n" 
1344                "- dst mac fail     : %d\n" 
1345                "- channel full     : %d\n" 
1346                "- broadcast        : %d\n",
1347                received,
1348                too_small,
1349                too_big,
1350                fifo_full,
1351                crc_fail,
1352                dst_fail,
1353                ch_full,
1354                broadcast );
1355    } 
1356    else
1357    {
1358        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
1359        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
1360        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
1361        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
1362        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
1363        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
1364
1365        _printf("\n### Network Controller TX Statistics ###\n"
1366                "- packets received : %d\n"
1367                "- too small        : %d\n"
1368                "- too big          : %d\n"
1369                "- src mac fail     : %d\n" 
1370                "- bypass           : %d\n" 
1371                "- broadcast        : %d\n",
1372                received,
1373                too_big,
1374                too_small,
1375                src_fail,
1376                bypass,
1377                broadcast );
1378    }
1379    return 0;
[494]1380}  // end _sys_nic_stats()
[459]1381
[440]1382/////////////////////////////////////////////////////////////////////////////////////////
1383//    FBF related syscall handlers
1384/////////////////////////////////////////////////////////////////////////////////////////
1385
1386/////////////////////////////////////////////
1387int _sys_fbf_sync_write( unsigned int offset,
1388                         void*        buffer,
1389                         unsigned int length )
1390{
1391    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1392    memcpy( fbf_address, buffer, length);
1393
1394    return 0;
1395}
1396
1397/////////////////////////////////////////////
1398int _sys_fbf_sync_read(  unsigned int offset,
1399                         void*        buffer,
1400                         unsigned int length )
1401{
1402    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1403    memcpy( buffer, fbf_address, length);
1404
1405    return 0;
1406}
1407
1408////////////////////////
1409int _sys_fbf_cma_alloc()
1410{
1411   // get a new CMA channel index
[459]1412    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
[440]1413
1414    if ( channel >= NB_CMA_CHANNELS )
1415    {
1416        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
1417        return -1;
1418    }
1419    else
1420    {
[449]1421        _set_context_slot( CTX_CMA_FB_ID, channel );
1422        return 0;
[440]1423    }
1424} // end sys_fbf_cma_alloc()
1425
[614]1426
1427////////////////////////
1428int _sys_fbf_cma_init_buf(void*        buf0_vbase, 
1429                          void*        buf1_vbase, 
1430                          void*        sts0_vaddr,
1431                          void*        sts1_vaddr )
[440]1432{
1433#if NB_CMA_CHANNELS > 0
1434
1435    unsigned int       vaddr;           // virtual address
[528]1436    unsigned int       flags;           // for _v2p_translate()
[614]1437    unsigned long long fbf_paddr;       // fbf physical address
1438    unsigned long long fbf_sts_paddr;   // fbf status physical address
1439    unsigned long long buf0_pbase;      // buffer 0 base physical address
1440    unsigned long long sts0_paddr;      // buffer 0 status physical address
1441    unsigned long long buf1_pbase;      // buffer 1 base physical address
1442    unsigned long long sts1_paddr;      // buffer 1 status physical address
[440]1443
1444    // get channel index
[449]1445    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]1446
1447    if ( channel >= NB_CMA_CHANNELS )
1448    {
[614]1449        _printf("\n[GIET ERROR] in _fbf_cma_init_buf() : CMA channel index too large\n");
[440]1450        return -1;
1451    }
1452
1453#if GIET_DEBUG_FBF_CMA
[614]1454_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_init_buf()\n"
1455        " - channel           = %d\n"
1456        " - buf0        vbase = %x\n"
1457        " - buf1        vbase = %x\n"
1458        " - sts0        vaddr = %x\n"
1459        " - sts1        vaddr = %x\n",
[440]1460        channel,
[614]1461        (unsigned int)buf0_vbase,
1462        (unsigned int)buf1_vbase,
1463        (unsigned int)sts0_vaddr,
1464        (unsigned int)sts1_vaddr );
[440]1465#endif
1466
[614]1467    // checking user buffers virtual addresses alignment
1468    if ( ((unsigned int)buf0_vbase & 0x3F) || 
1469         ((unsigned int)buf1_vbase & 0x3F) ) 
[440]1470    {
[614]1471        _printf("\n[GIET ERROR] in _fbf_cma_inti_buf() : user buffer not aligned\n");
[440]1472        return -1;
1473    }
1474
[614]1475    // checking user buffers status virtual addresses alignment
1476    if ( ((unsigned int)sts0_vaddr & 0x3F) ||
1477         ((unsigned int)sts1_vaddr & 0x3F) )
1478    {
1479        _printf("\n[GIET ERROR] in _fbf_cma_init_buf() : user buffer status not aligned\n");
1480        return -1;
1481    }
1482
[440]1483    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
[528]1484    vaddr = (unsigned int)SEG_FBF_BASE;
[614]1485    fbf_paddr = _v2p_translate( vaddr , &flags );
1486    vaddr = (unsigned int)&_fbf_status[channel];
1487    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
[440]1488
[614]1489    _fbf_chbuf[channel].fbf_desc =
1490        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
1491        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
1492
[528]1493    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
[614]1494    vaddr = (unsigned int)buf0_vbase;
1495    buf0_pbase = _v2p_translate( vaddr , &flags );
[440]1496    if ((flags & PTE_U) == 0) 
1497    {
[528]1498        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf0 not in user space\n");
[440]1499        return -1;
1500    }
1501
[614]1502    vaddr = (unsigned int)sts0_vaddr;
1503    sts0_paddr = _v2p_translate( vaddr , &flags );
1504    if ((flags & PTE_U) == 0) 
1505    {
1506        _printf("\n[GIET ERROR] in _fbf_cma_start() : sts0 not in user space\n");
1507        return -1;
1508    }
1509
1510    _fbf_chbuf[channel].buf0_desc = 
1511        (unsigned long long) ((sts0_paddr & 0xFFFFFFFFULL) >> 6) +
1512        (((buf0_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1513
[528]1514    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
[614]1515    vaddr = (unsigned int)buf1_vbase;
1516    buf1_pbase = _v2p_translate( vaddr , &flags );
[440]1517    if ((flags & PTE_U) == 0) 
1518    {
[528]1519        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf1 not in user space\n");
[440]1520        return -1;
1521    }
1522
[614]1523    vaddr = (unsigned int)sts1_vaddr;
1524    sts1_paddr = _v2p_translate( vaddr , &flags );
1525    if ((flags & PTE_U) == 0) 
1526    {
1527        _printf("\n[GIET ERROR] in _fbf_cma_start() : sts1 not in user space\n");
1528        return -1;
1529    }
[440]1530
[614]1531    _fbf_chbuf[channel].buf1_desc = 
1532        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
1533        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1534
[505]1535    // Compute and register physical adress of the fbf_chbuf descriptor
[528]1536    vaddr = (unsigned int)&_fbf_chbuf[channel];
1537    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
[440]1538 
[614]1539#if GIET_DEBUG_FBF_CMA
1540_printf(" - fbf         pbase = %l\n"
1541        " - fbf status  paddr = %l\n"
1542        " - buf0        pbase = %l\n"
1543        " - buf0 status paddr = %l\n" 
1544        " - buf1        pbase = %l\n"
1545        " - buf0 status paddr = %l\n" 
1546        " - chbuf       pbase = %l\n",
1547        fbf_paddr,
1548        fbf_sts_paddr,
1549        buf0_pbase,
1550        sts0_paddr,
1551        buf1_pbase,
1552        sts1_paddr,
1553        _fbf_chbuf_paddr[channel] );
1554#endif
1555
1556    return 0;
1557
1558#else
1559
1560    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
1561    return -1;
1562
1563#endif 
1564} // end sys_fbf_cma_init_buf()
1565
1566////////////////////////////////////////////
1567int _sys_fbf_cma_start( unsigned int length ) 
1568{
1569#if NB_CMA_CHANNELS > 0
1570
1571    // get channel index
1572    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1573
1574    if ( channel >= NB_CMA_CHANNELS )
1575    {
1576        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
1577        return -1;
1578    }
1579
1580    // check buffers initialization
1581    if ( ( _fbf_chbuf[channel].buf0_desc == 0x0ULL ) &&
1582         ( _fbf_chbuf[channel].buf1_desc == 0x0ULL) &&
1583         ( _fbf_chbuf[channel].fbf_desc == 0x0ULL) )
1584    {
1585        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
1586                "Buffer initialization has not been done\n");
1587        return -1;
1588    }
1589
1590    // initializes buffer length
1591    _fbf_chbuf[channel].length = length;
1592
[440]1593    if ( USE_IOB )
1594    {
[505]1595        // SYNC request for fbf_chbuf descriptor
1596        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
[440]1597    }
1598
[505]1599    // start CMA transfer
1600    unsigned long long paddr = _fbf_chbuf_paddr[channel];
1601    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
1602    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
[614]1603    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
[505]1604    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
1605
1606    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
1607    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
1608    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
1609    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
1610    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
1611    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
1612    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
1613    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
1614    _cma_set_register( channel, CHBUF_RUN      , 1 );
1615
[440]1616    return 0;
1617
1618#else
1619
1620    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1621    return -1;
1622
1623#endif
1624} // end _sys_fbf_cma_start()
1625
1626/////////////////////////////////////////////////////
1627int _sys_fbf_cma_display( unsigned int buffer_index )
1628{
1629#if NB_CMA_CHANNELS > 0
1630
[505]1631    volatile unsigned int full = 1;
[440]1632
1633    // get channel index
[449]1634    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]1635
1636    if ( channel >= NB_CMA_CHANNELS )
1637    {
[505]1638        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1639                "CMA channel index too large\n");
[440]1640        return -1;
1641    }
1642
[505]1643    // get fbf_chbuf descriptor pointer
1644    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1645
[440]1646#if GIET_DEBUG_FBF_CMA
1647_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
[614]1648        " - cma channel      = %d\n"
1649        " - buffer index     = %d\n"
1650        " - buf0_desc value  = %l\n"
1651        " - buf1_desc value  = %l\n"
1652        " - fbf_desc  value  = %l\n",
[505]1653        channel , buffer_index,
[614]1654        _fbf_chbuf[channel].buf0_desc,
1655        _fbf_chbuf[channel].buf1_desc,
1656        _fbf_chbuf[channel].fbf_desc );
[440]1657#endif
1658
[614]1659    unsigned long long buf_sts_paddr;
1660    unsigned long long buf_paddr;
1661    unsigned long long fbf_sts_paddr;
1662
[478]1663    if ( buffer_index == 0 )    // user buffer 0
1664    {
[614]1665        buf_sts_paddr =
1666            ((pdesc->buf0_desc & 0xFFF0000000000000ULL) >> 20) + // compute address extension
1667            ((pdesc->buf0_desc & 0x3FFFFFFULL) << 6);            // compute 32 LSB of the address
[505]1668
[614]1669        buf_paddr =
1670            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
[440]1671    }
[478]1672    else                        // user buffer 1
1673    {
[614]1674        buf_sts_paddr =
1675            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
1676            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
[505]1677
[614]1678        buf_paddr =
1679            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
1680    }
[478]1681
[614]1682    fbf_sts_paddr =
1683        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
1684        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
[440]1685
[614]1686#if GIET_DEBUG_FBF_CMA
1687_printf(" - fbf status paddr = %l\n"
1688        " - buf        pbase = %l\n"
1689        " - buf status paddr = %l\n",
1690        fbf_sts_paddr,
1691        buf_paddr,
1692        buf_sts_paddr );
1693#endif
1694       
1695    // waiting user buffer released by the CMA component)
1696    while ( full )
1697    { 
1698        // INVAL L2 cache copy of user buffer descriptor,
1699        // because it has been modified in RAM by the CMA component
1700        _mmc_inval( buf_sts_paddr , 4 );       
[440]1701
[614]1702        full = _physical_read( buf_sts_paddr );
[440]1703    }
1704
[614]1705    // SYNC request for the user buffer, because
1706    // it will be read from XRAM by the CMA component
1707    _mmc_sync( buf_paddr , pdesc->length );
[440]1708
[614]1709    // set user buffer status
1710    _physical_write( buf_sts_paddr, 0x1 );
1711
1712    // reset fbf buffer status
1713    _physical_write( fbf_sts_paddr, 0x0 );
1714   
1715    // SYNC request, because these buffer descriptors
1716    // will be read from XRAM by the CMA component
1717    _mmc_sync( buf_sts_paddr, 4 );
1718    _mmc_sync( fbf_sts_paddr, 4 );
1719
[440]1720    return 0;
1721
1722#else
1723
1724    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1725    return -1;
1726
1727#endif
1728} // end _sys_fbf_cma_display()
1729
1730///////////////////////
1731int _sys_fbf_cma_stop()
1732{
1733#if NB_CMA_CHANNELS > 0
1734
1735    // get channel index
[449]1736    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]1737
1738    if ( channel >= NB_CMA_CHANNELS )
1739    {
1740        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
1741        return -1;
1742    }
1743
1744    // Desactivate CMA channel
[505]1745    _cma_set_register( channel, CHBUF_RUN, 0 );
[440]1746
1747    return 0;
1748
1749#else
1750
1751    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
1752    return -1;
1753
1754#endif
1755} // end _sys_fbf_cma_stop()
1756
1757
1758//////////////////////////////////////////////////////////////////////////////
1759//           Miscelaneous syscall handlers
1760//////////////////////////////////////////////////////////////////////////////
1761
1762///////////////
1763int _sys_ukn() 
1764{
1765    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
1766    return -1;
1767}
1768
1769////////////////////////////////////
1770int _sys_proc_xyp( unsigned int* x,
1771                   unsigned int* y,
1772                   unsigned int* p )
1773{
[428]1774    unsigned int gpid = _get_procid();  // global processor index from CPO register
1775
1776    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
1777    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1778    *p = gpid & ((1<<P_WIDTH)-1);
[440]1779
1780    return 0;
[428]1781}
[440]1782
1783//////////////////////////////////
1784int _sys_task_exit( char* string ) 
[258]1785{
[294]1786    unsigned int date       = _get_proctime();
[428]1787
1788    unsigned int gpid       = _get_procid();
1789    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]1790    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
1791    unsigned int x          = cluster_xy >> Y_WIDTH;
[629]1792    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[428]1793
[629]1794    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
[258]1795
[440]1796    // print exit message
[294]1797    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
1798            "\n       Cause : %s\n\n",
[629]1799            ltid, x, y, p, date, string );
[258]1800
[629]1801    // set NORUN_MASK_TASK bit (non runnable state)
1802    static_scheduler_t*  psched  = (static_scheduler_t*)_schedulers[x][y][p];
1803    unsigned int*        ptr     = &psched->context[ltid][CTX_NORUN_ID];
1804    _atomic_or( ptr , NORUN_MASK_TASK );
[258]1805
1806    // deschedule
[528]1807    _sys_context_switch();
[440]1808
1809    return 0;
[258]1810} 
1811
[629]1812///////////////////////////////////////
1813int _sys_kill_application( char* name )
1814{
1815    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1816    mapping_vspace_t * vspace  = _get_vspace_base(header);
1817    mapping_task_t   * task    = _get_task_base(header);
1818
1819    unsigned int vspace_id;
1820    unsigned int task_id;
1821    unsigned int y_size = header->y_size;
1822
1823    // scan vspaces
1824    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1825    {
1826        if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 
1827        {
1828            // scan tasks in vspace
1829            for (task_id = vspace[vspace_id].task_offset; 
1830                 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 
1831                 task_id++) 
1832            {
1833                unsigned int cid   = task[task_id].clusterid;
1834                unsigned int x     = cid / y_size;
1835                unsigned int y     = cid % y_size;
1836                unsigned int p     = task[task_id].proclocid;
1837                unsigned int ltid  = task[task_id].ltid;
1838
1839                // set NORUN_MASK_TASK bit
1840                static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
1841                unsigned int*       ptr     = &psched->context[ltid][CTX_NORUN_ID];
1842                _atomic_or( ptr , NORUN_MASK_TASK );
1843            } 
1844            return 0;
1845        }
1846    } 
1847    return -1;    // not found
1848}
1849   
1850///////////////////////////////////////
1851int _sys_exec_application( char* name )
1852{
1853    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1854    mapping_vspace_t * vspace  = _get_vspace_base(header);
1855    mapping_task_t   * task    = _get_task_base(header);
1856    mapping_vseg_t   * vseg    = _get_vseg_base(header);
1857
1858    unsigned int vspace_id;
1859    unsigned int task_id;
1860    unsigned int vseg_id;
1861
1862    unsigned int y_size = header->y_size;
1863
1864    // scan vspaces
1865    for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++) 
1866    {
1867        if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 
1868        {
1869            // scan tasks in vspace
1870            for (task_id = vspace[vspace_id].task_offset; 
1871                 task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks); 
1872                 task_id++) 
1873            {
1874                unsigned int cid   = task[task_id].clusterid;
1875                unsigned int x     = cid / y_size;
1876                unsigned int y     = cid % y_size;
1877                unsigned int p     = task[task_id].proclocid;
1878                unsigned int ltid  = task[task_id].ltid;
1879
1880                // compute stack pointer value (sp_value)
1881                vseg_id = task[task_id].stack_vseg_id;
1882                unsigned int sp_value = vseg[vseg_id].vbase + vseg[vseg_id].length;
1883
1884                // compute task entry point value (epc_value)
1885                vseg_id = vspace[vspace_id].start_vseg_id;     
1886                unsigned int* vaddr = (unsigned int*)( vseg[vseg_id].vbase + 
1887                                                       ((task[task_id].startid)<<2) );
1888                unsigned int  epc_value = *vaddr;
1889
1890                // compute reurn address value (ra_value)
1891                unsigned int ra_value = (unsigned int)(&_ctx_eret);
1892
1893                // get scheduler pointer
1894                static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
1895
1896                // initialise task context: RA / SR / EPC / SP / NORUN slots
1897                psched->context[ltid][CTX_RA_ID]    = ra_value;
1898                psched->context[ltid][CTX_SR_ID]    = GIET_SR_INIT_VALUE;
1899                psched->context[ltid][CTX_SP_ID]    = sp_value;
1900                psched->context[ltid][CTX_EPC_ID]   = epc_value;
1901                psched->context[ltid][CTX_NORUN_ID] = 0;
1902            } 
1903            return 0;
1904        }
1905    }
1906    return -1;    // not found
1907}
1908   
[528]1909/////////////////////////
1910int _sys_context_switch() 
[258]1911{
[440]1912    unsigned int save_sr;
[258]1913
[440]1914    _it_disable( &save_sr );
1915    _ctx_switch();
1916    _it_restore( &save_sr );
1917
1918    return 0;
[258]1919}
1920
[440]1921////////////////////////
1922int _sys_local_task_id()
[258]1923{
1924    return _get_context_slot(CTX_LTID_ID);
1925}
1926
[440]1927/////////////////////////
1928int _sys_global_task_id()
[258]1929{
1930    return _get_context_slot(CTX_GTID_ID);
1931}
1932
[440]1933////////////////////
1934int _sys_thread_id()
[267]1935{
1936    return _get_context_slot(CTX_TRDID_ID);
1937}
1938
[494]1939////////////////////////////////////////////
1940int _sys_procs_number( unsigned int* x_size,
1941                       unsigned int* y_size,
1942                       unsigned int* nprocs )
[258]1943{
[494]1944    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[440]1945    mapping_cluster_t * cluster = _get_cluster_base(header);
1946
[494]1947    unsigned int x;
1948    unsigned int y;
1949    unsigned int okmin = 1;
1950    unsigned int okmax = 1;
1951
1952    // compute max values
1953    unsigned int xmax  = header->x_size;
1954    unsigned int ymax  = header->y_size;
1955    unsigned int procs = cluster[0].procs;
1956
1957    // check the (ymax-1) lower rows
1958    for ( y = 0 ; y < ymax-1 ; y++ )
[440]1959    {
[494]1960        for ( x = 0 ; x < xmax ; x++ )
1961        {
1962            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
1963        }
[440]1964    }
[494]1965
1966    // check the upper row
1967    for ( x = 0 ; x < xmax ; x++ )
[440]1968    {
[494]1969        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
[440]1970    }
[494]1971
1972    // return values
1973    if ( okmin && okmax )
1974    {
1975        *x_size = xmax;
1976        *y_size = ymax;
1977        *nprocs = procs;
1978    }
1979    else if ( okmin )
1980    {
1981        *x_size = xmax;
1982        *y_size = ymax-1;
1983        *nprocs = procs;
1984    }
1985    else
1986    {
1987        *x_size = 0;
1988        *y_size = 0;
1989        *nprocs = 0;
1990    }
1991    return 0;
[440]1992}
1993
1994///////////////////////////////////////////////////////
[516]1995int _sys_vseg_get_vbase( char*             vspace_name, 
1996                         char*             vseg_name, 
[440]1997                         unsigned int*     vbase ) 
1998{
[322]1999    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]2000    mapping_vspace_t * vspace = _get_vspace_base(header);
[516]2001    mapping_vseg_t * vseg     = _get_vseg_base(header);
[258]2002
2003    unsigned int vspace_id;
[516]2004    unsigned int vseg_id;
[258]2005
2006    // scan vspaces
2007    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
2008    {
2009        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2010        {
[516]2011            // scan vsegs
2012            for (vseg_id = vspace[vspace_id].vseg_offset; 
2013                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
2014                 vseg_id++) 
[258]2015            {
[516]2016                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
[258]2017                {
[516]2018                    *vbase = vseg[vseg_id].vbase;
[258]2019                    return 0;
2020                }
2021            } 
2022        }
2023    } 
[440]2024    return -1;    // not found
[258]2025}
2026
[440]2027/////////////////////////////////////////////////////////
[516]2028int _sys_vseg_get_length( char*         vspace_name, 
2029                          char*         vseg_name,
[440]2030                          unsigned int* length ) 
[258]2031{
[440]2032    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2033    mapping_vspace_t * vspace = _get_vspace_base(header);
[516]2034    mapping_vseg_t * vseg     = _get_vseg_base(header);
[258]2035
[440]2036    unsigned int vspace_id;
[516]2037    unsigned int vseg_id;
[440]2038
2039    // scan vspaces
2040    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
[258]2041    {
[440]2042        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2043        {
[516]2044            // scan vsegs
2045            for (vseg_id = vspace[vspace_id].vseg_offset; 
2046                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
2047                 vseg_id++) 
[440]2048            {
[516]2049                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
[440]2050                {
[516]2051                    *length = vseg[vseg_id].length;
[440]2052                    return 0;
2053                }
2054            } 
2055        }
2056    } 
2057    return -1;    // not found
[258]2058}
2059
[440]2060////////////////////////////////////////
2061int _sys_xy_from_ptr( void*         ptr,
2062                      unsigned int* x,
2063                      unsigned int* y )
[396]2064{
2065    unsigned int flags;
[528]2066    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
[396]2067   
[528]2068    *x = (paddr>>36) & 0xF;
2069    *y = (paddr>>32) & 0xF;
[396]2070
2071    return 0;
2072}
2073
[440]2074/////////////////////////////////////////
2075int _sys_heap_info( unsigned int* vaddr, 
2076                    unsigned int* length,
2077                    unsigned int  x,
2078                    unsigned int  y ) 
[258]2079{
[440]2080    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[516]2081    mapping_task_t *   task    = _get_task_base(header);
2082    mapping_vseg_t *   vseg    = _get_vseg_base(header);
2083    mapping_vspace_t * vspace  = _get_vspace_base(header);
[294]2084
[440]2085    unsigned int task_id;
2086    unsigned int vspace_id;
[516]2087    unsigned int vseg_id = 0xFFFFFFFF;
[258]2088
[516]2089    // searching the heap vseg
[440]2090    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
2091    {
2092        // get vspace global index
2093        vspace_id = _get_context_slot(CTX_VSID_ID);
2094
2095        // scan all tasks in vspace
[516]2096        unsigned int min = vspace[vspace_id].task_offset ;
2097        unsigned int max = min + vspace[vspace_id].tasks ;
[440]2098        for ( task_id = min ; task_id < max ; task_id++ )
2099        {
[516]2100            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
[440]2101            {
[516]2102                vseg_id = task[task_id].heap_vseg_id;
2103                if ( vseg_id != 0xFFFFFFFF ) break;
[440]2104            }
2105        }
2106    }
2107    else                                // searching in the calling task
2108    {
2109        task_id = _get_context_slot(CTX_GTID_ID);
[516]2110        vseg_id = task[task_id].heap_vseg_id;
[440]2111    }
2112
[516]2113    // analysing the vseg_id
2114    if ( vseg_id != 0xFFFFFFFF ) 
[440]2115    {
[516]2116        *vaddr  = vseg[vseg_id].vbase;
2117        *length = vseg[vseg_id].length;
[440]2118        return 0;
2119    }
2120    else 
2121    {
2122        *vaddr  = 0;
2123        *length = 0;
2124        return -1;
2125    }
2126}  // end _sys_heap_info()
2127
2128
[258]2129// Local Variables:
2130// tab-width: 4
2131// c-basic-offset: 4
2132// c-file-offsets:((innamespace . 0)(inline-open . 0))
2133// indent-tabs-mode: nil
2134// End:
2135// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
2136
Note: See TracBrowser for help on using the repository browser.