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

Last change on this file since 631 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
Line 
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>
12#include <mmc_driver.h>
13#include <mwr_driver.h>
14#include <cma_driver.h>
15#include <ctx_handler.h>
16#include <fat32.h>
17#include <utils.h>
18#include <kernel_malloc.h>
19#include <tty0.h>
20#include <vmem.h>
21#include <hard_config.h>
22#include <giet_config.h>
23#include <mapping_info.h>
24#include <irq_handler.h>
25#include <io.h>
26
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
31#if !defined(NB_TTY_CHANNELS)
32# error: You must define NB_TTY_CHANNELS in the hard_config.h file
33#endif
34
35#if (NB_TTY_CHANNELS < 1)
36# error: NB_TTY_CHANNELS cannot be smaller than 1!
37#endif
38
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
51#if !defined(GIET_NO_HARD_CC)
52# error: You must define GIET_NO_HARD_CC in the giet_config.h file
53#endif
54
55#if !defined ( GIET_NIC_MAC4 )
56# error: You must define GIET_NIC_MAC4 in the giet_config.h file
57#endif
58
59#if !defined ( GIET_NIC_MAC2 )
60# error: You must define GIET_NIC_MAC2 in the giet_config.h file
61#endif
62
63////////////////////////////////////////////////////////////////////////////
64//        Extern variables
65////////////////////////////////////////////////////////////////////////////
66
67// allocated in tty0.c file.
68extern sqt_lock_t _tty0_sqt_lock;
69
70// allocated in mwr_driver.c file.
71extern simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
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];
77
78
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
83// allocated in kernel_init.c file
84extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
85
86////////////////////////////////////////////////////////////////////////////
87//     Channel allocators for peripherals
88//     (TTY[0] is reserved for kernel)
89////////////////////////////////////////////////////////////////////////////
90
91__attribute__((section(".kdata")))
92unsigned int _tty_channel_allocator    = 1;
93
94__attribute__((section(".kdata")))
95unsigned int _tim_channel_allocator    = 0;
96
97__attribute__((section(".kdata")))
98unsigned int _cma_channel_allocator    = 0;
99
100__attribute__((section(".kdata")))
101unsigned int _nic_rx_channel_allocator = 0;
102
103__attribute__((section(".kdata")))
104unsigned int _nic_tx_channel_allocator = 0;
105
106////////////////////////////////////////////////////////////////////////////
107//     NIC_RX and NIC_TX kernel chbuf arrays
108////////////////////////////////////////////////////////////////////////////
109
110__attribute__((section(".kdata")))
111ker_chbuf_t  _nic_ker_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
112
113__attribute__((section(".kdata")))
114ker_chbuf_t  _nic_ker_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
115
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.
119// FBF status
120////////////////////////////////////////////////////////////////////////////
121
122__attribute__((section(".kdata")))
123fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
124
125__attribute__((section(".kdata")))
126unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
127
128__attribute__((section(".kdata")))
129buffer_status_t _fbf_status[NB_CMA_CHANNELS] __attribute__((aligned(64)));
130
131////////////////////////////////////////////////////////////////////////////
132//    Initialize the syscall vector with syscall handlers
133// Note: This array must be synchronised with the define in file stdio.h
134////////////////////////////////////////////////////////////////////////////
135
136__attribute__((section(".kdata")))
137const void * _syscall_vector[64] = 
138{
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 */
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 */
155
156    &_sys_procs_number,              /* 0x10 */
157    &_sys_fbf_sync_write,            /* 0x11 */
158    &_sys_fbf_sync_read,             /* 0x12 */
159    &_sys_thread_id,                 /* 0x13 */
160    &_sys_tim_alloc,                 /* 0x14 */
161    &_sys_tim_start,                 /* 0x15 */ 
162    &_sys_tim_stop,                  /* 0x16 */
163    &_sys_kill_application,          /* 0x17 */
164    &_sys_exec_application,          /* 0x18 */   
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 */
172
173    &_fat_open,                      /* 0x20 */
174    &_fat_read,                      /* 0x21 */
175    &_fat_write,                     /* 0x22 */
176    &_fat_lseek,                     /* 0x23 */
177    &_fat_file_info,                 /* 0x24 */
178    &_fat_close,                     /* 0x25 */
179    &_fat_remove,                    /* 0x26 */
180    &_fat_rename,                    /* 0x27 */
181    &_fat_mkdir,                     /* 0x28 */
182    &_fat_list,                      /* 0x29 */
183    &_sys_ukn,                       /* 0x2A */
184    &_sys_ukn,                       /* 0x2B */
185    &_sys_ukn,                       /* 0x2C */
186    &_sys_ukn,                       /* 0x2D */
187    &_sys_ukn,                       /* 0x2E */
188    &_sys_ukn,                       /* 0x2F */
189
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 */
206};
207
208
209//////////////////////////////////////////////////////////////////////////////
210//           Coprocessors related syscall handlers
211//////////////////////////////////////////////////////////////////////////////
212
213//////////////////////////////////////////////////
214int _sys_coproc_alloc( unsigned int   coproc_type,
215                       unsigned int*  coproc_info )
216{
217    // In this implementation, the allocation policy is constrained:
218    // the coprocessor must be in the same cluster as the calling task,
219    // and there is at most one coprocessor per cluster
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);
229    unsigned int cluster_id = x * Y_SIZE + y;
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] );
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
258        // returns coprocessor info
259        *coproc_info = _coproc_info[cluster_id];
260
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
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",
268        x , y , *coproc_info , cluster_xy );
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
281////////////////////////////////////////////////////////
282int _sys_coproc_release( unsigned int coproc_reg_index )
283{
284    // processor coordinates
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);
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 )
293    {
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 ); 
297         return -1;
298    }
299
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;
307
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    }
314
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
321#if GIET_DEBUG_COPROC
322_printf("\n[GIET DEBUG COPROC] _sys_coproc_release() in cluster[%d,%d]\n",
323        cx, cy );
324#endif
325
326    return 0;
327}  // end _sys_coproc_release()
328
329//////////////////////////////////////////////////////////////
330int _sys_coproc_channel_init( unsigned int            channel,
331                              giet_coproc_channel_t*  desc )
332{
333    // processor coordinates
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);
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 )
342    {
343         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
344                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
345                 x , y , p ); 
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    {
355         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
356                 " illegal mode\n");
357         return -1;
358    }
359
360    // get memory buffer size
361    unsigned int size = desc->buffer_size;
362 
363    // physical addresses
364    unsigned long long buffer_paddr;
365    unsigned int       buffer_lsb;
366    unsigned int       buffer_msb;
367    unsigned long long mwmr_paddr = 0;
368    unsigned int       mwmr_lsb;
369    unsigned int       mwmr_msb;
370    unsigned long long lock_paddr = 0;
371    unsigned int       lock_lsb;
372    unsigned int       lock_msb;
373
374    unsigned int       flags;     // unused
375
376    // compute memory buffer physical address
377    buffer_paddr = _v2p_translate( desc->buffer_vaddr , &flags );
378    buffer_lsb   = (unsigned int)buffer_paddr;
379    buffer_msb   = (unsigned int)(buffer_paddr>>32); 
380
381    // call MWMR_DMA driver
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 ); 
386                       
387    if ( mode == MODE_MWMR )
388    {
389        // compute MWMR descriptor physical address
390        mwmr_paddr = _v2p_translate( desc->mwmr_vaddr , &flags );
391        mwmr_lsb = (unsigned int)mwmr_paddr;
392        mwmr_msb = (unsigned int)(mwmr_paddr>>32); 
393
394        // call MWMR_DMA driver
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 ); 
397
398        // compute lock physical address
399        lock_paddr = _v2p_translate( desc->lock_vaddr , &flags );
400        lock_lsb = (unsigned int)lock_paddr;
401        lock_msb = (unsigned int)(lock_paddr>>32); 
402
403        // call MWMR_DMA driver
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 ); 
406    }
407
408#if GIET_DEBUG_COPROC
409_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_init() for coproc[%d,%d]\n"
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
419////////////////////////////////////////////////////
420int _sys_coproc_run( unsigned int coproc_reg_index )
421{
422    // processor coordinates
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);
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 )
431    {
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 ); 
435         return -1;
436    }
437
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;
446
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 );
452
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;
465
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    }
471
472    //////////////////////////////////////////////////////////////////////////
473    if ( (mode == MODE_MWMR) || (mode == MODE_DMA_NO_IRQ) )  // no descheduling
474    {
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;
488    }
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;
495
496        // enters critical section
497        unsigned int save_sr;
498        _it_disable( &save_sr ); 
499
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 );
504
505        // start coprocessor
506        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
507
508#if GIET_DEBUG_COPROC
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() );
511#endif
512
513        // deschedule task
514        _ctx_switch(); 
515
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()
532{
533    // processor coordinates
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);
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 )
542    {
543         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
544                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
545                 x , y , p ); 
546         return -1;
547    }
548
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];
553
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
598#if GIET_DEBUG_COPROC
599_printf("\n[GIET DEBUG COPROC] _sys_coproc_completed() for coprocessor[%d,%d] error = %d\n", 
600        cx , cy , error );
601#endif
602
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    }
611} // end _sys_coproc_completed()
612
613
614//////////////////////////////////////////////////////////////////////////////
615//             TTY related syscall handlers
616//////////////////////////////////////////////////////////////////////////////
617
618////////////////////
619int _sys_tty_alloc()
620{
621    // get a new TTY terminal index
622    unsigned int channel = _atomic_increment( &_tty_channel_allocator, 1 );
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    }
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;
641}
642
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///////////////////////////////////////////
694int _sys_tty_get_lock( unsigned int   channel,       // unused
695                       unsigned int * save_sr_ptr )
696{
697    // check tty channel
698    if( channel != 0 )  return 1;
699
700    _it_disable( save_sr_ptr );
701    _sqt_lock_acquire( &_tty0_sqt_lock );
702    return 0;
703}
704
705///////////////////////////////////////////////
706int _sys_tty_release_lock( unsigned int   channel,
707                           unsigned int * save_sr_ptr )
708{
709    // check tty channel
710    if( channel != 0 )  return 1;
711
712    _sqt_lock_release( &_tty0_sqt_lock );
713    _it_restore( save_sr_ptr );
714    return 0;
715}
716
717//////////////////////////////////////////////////////////////////////////////
718//             TIM related syscall handlers
719//////////////////////////////////////////////////////////////////////////////
720
721////////////////////
722int _sys_tim_alloc()
723{
724    // get a new timer index
725    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
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    {
734        _set_context_slot( CTX_TIM_ID, channel );
735        return 0;
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
777#define NIC_CONTAINER_SIZE 4096
778
779////////////////////////////////////////
780int _sys_nic_alloc( unsigned int is_rx,
781                    unsigned int xmax,
782                    unsigned int ymax )
783{
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    }
795
796    ////////////////////////////////////////////////////////
797    // Step 1: get and register CMA and NIC channel index //
798    ////////////////////////////////////////////////////////
799
800    // get a NIC_RX or NIC_TX channel index
801    unsigned int nic_channel;
802    unsigned int cma_channel;
803
804    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
805    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
806
807    if ( (nic_channel >= NB_NIC_CHANNELS) )
808    {
809        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
810        return -1;
811    }
812
813    // get a CMA channel index
814    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
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    }
821
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"
825        "  nic_channel = %d / cma_channel = %d\n",
826        thread , _get_proctime() , nic_channel , cma_channel );
827#endif
828
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    }
835    else
836    {
837        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
838        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
839    }
840
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
847    // physical addresses to be registered in the CMA registers
848    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
849    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
850
851    // allocate one kernel container and one status variable per cluster in the
852    // (xmax / ymax) mesh
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
858    unsigned long long  sts_paddr;          // container status physical address
859
860    unsigned int        flags;              // for _v2p_translate()
861
862    for ( cx = 0 ; cx < xmax ; cx++ )
863    {
864        for ( cy = 0 ; cy < ymax ; cy++ )
865        {
866            // compute index in chbuf
867            index = (cx * ymax) + cy; 
868
869            // allocate the kernel container
870            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
871
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
879            // compute container physical address
880            cont_paddr = _v2p_translate( vaddr , &flags );
881
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
919            // initialize chbuf entry
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);
936
937#if GIET_DEBUG_NIC
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) );
944#endif
945        }
946    }
947
948    // complete kernel chbuf initialisation
949    if ( is_rx )
950    {
951        _nic_ker_rx_chbuf[nic_channel].xmax = xmax;
952        _nic_ker_rx_chbuf[nic_channel].ymax = ymax;
953    }
954    else
955    {
956        _nic_ker_tx_chbuf[nic_channel].xmax = xmax;
957        _nic_ker_tx_chbuf[nic_channel].ymax = ymax;
958    }
959
960    // compute the kernel chbuf descriptor physical address
961    if ( is_rx ) vaddr = (unsigned int)( &_nic_ker_rx_chbuf[nic_channel] );
962    else         vaddr = (unsigned int)( &_nic_ker_tx_chbuf[nic_channel] );
963
964    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
965
966#if GIET_DEBUG_NIC
967_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
968        "  vaddr = %x / paddr = %l\n",
969        thread , vaddr , ker_chbuf_pbase );
970#endif
971
972    // sync the kernel chbuf in L2 after write in L2
973    _mmc_sync( ker_chbuf_pbase, sizeof( ker_chbuf_t ) );
974
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
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) );
1001        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
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) );
1007        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
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
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 );
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",
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
1060    // start CMA transfer
1061    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
1062    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
1063    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
1064
1065    // activates NIC channel
1066    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 );
1067
1068#if GIET_DEBUG_NIC
1069    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
1070            thread , _get_proctime() );
1071#endif
1072
1073    return 0;
1074}  // end _sys_nic_start()
1075
1076
1077//////////////////////////////////////
1078int _sys_nic_move( unsigned int is_rx,
1079                   unsigned int channel,
1080                   void*        buffer )
1081{
1082
1083#if GIET_DEBUG_NIC
1084unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
1085_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
1086        thread , _get_proctime() );
1087#endif
1088
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
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];
1100
1101    // get xmax / ymax parameters
1102    unsigned int xmax = ker_chbuf->xmax;
1103    unsigned int ymax = ker_chbuf->ymax;
1104
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   
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   
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
1131
1132    // Compute user buffer physical address and check access rights
1133    usr_buf_paddr = _v2p_translate( (unsigned int)buffer , &flags );
1134
1135    if ( (flags & PTE_U) == 0 )
1136    {
1137        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
1138        return -1;
1139    }
1140
1141#if GIET_DEBUG_NIC
1142_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
1143        thread, usr_buf_paddr );
1144#endif
1145
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);
1151
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
1158    // poll local kernel container status until success
1159    while ( 1 )
1160    {
1161        // inval buffer descriptor in L2 before read in L2
1162        _mmc_inval( ker_sts_paddr, 4 );
1163        ker_sts = _physical_read( ker_sts_paddr );
1164
1165#if GIET_DEBUG_NIC
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 );
1169#endif
1170
1171        // test buffer status and break if found
1172        if ( ( is_rx != 0 ) && ( ker_sts == 0x1 ) ) break;
1173        if ( ( is_rx == 0 ) && ( ker_sts == 0 ) ) break;
1174    }
1175
1176    // compute kernel buffer physical address
1177    ker_buf_paddr = (ker_buf_desc & 0xFFFFFFFFFC000000ULL) >> 20;
1178   
1179    // move one container
1180    if ( is_rx )              // RX transfer
1181    {
1182        // inval kernel buffer in L2 before read in L2
1183        _mmc_inval( ker_buf_paddr, NIC_CONTAINER_SIZE );
1184
1185        // transfer data from kernel buffer to user buffer
1186        _physical_memcpy( usr_buf_paddr, 
1187                          ker_buf_paddr, 
1188                          NIC_CONTAINER_SIZE );
1189#if GIET_DEBUG_NIC
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",
1192        thread , ker_buf_paddr , usr_buf_paddr , _get_proctime() );
1193#endif
1194
1195    }
1196    else                      // TX transfer
1197    {
1198        // transfer data from user buffer to kernel buffer
1199        _physical_memcpy( ker_buf_paddr, 
1200                          usr_buf_paddr, 
1201                          NIC_CONTAINER_SIZE );
1202
1203        // sync kernel buffer in L2 after write in L2
1204        _mmc_sync( ker_buf_paddr, NIC_CONTAINER_SIZE );
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",
1209        thread , usr_buf_paddr , ker_buf_paddr , _get_proctime() );
1210#endif
1211
1212    }
1213
1214    // update kernel chbuf status
1215    if ( is_rx ) _physical_write ( ker_sts_paddr, 0 );
1216    else         _physical_write ( ker_sts_paddr, 0x1 );
1217
1218    // sync kernel chbuf in L2 after write in L2
1219    _mmc_sync( ker_sts_paddr, 4 );
1220
1221#if GIET_DEBUG_NIC
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() );
1224#endif
1225
1226    return 0;
1227} // end _sys_nic_move()
1228
1229
1230////////////////////////////////////////
1231int _sys_nic_stop( unsigned int is_rx,
1232                   unsigned int channel )
1233{
1234    unsigned int nic_channel;
1235    unsigned int cma_channel;
1236
1237    // get NIC channel index and CMA channel index
1238    if ( is_rx )
1239    {
1240        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1241        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
1242    }
1243    else
1244    {
1245        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1246        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1247    }
1248
1249    // check NIC and CMA channels index
1250    if ( nic_channel != channel )
1251    {
1252        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
1253        return -1;
1254    }
1255    if ( cma_channel >= NB_CMA_CHANNELS )
1256    {
1257        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
1258        return -1;
1259    }
1260
1261    // desactivates the NIC channel
1262    _nic_channel_stop( nic_channel, is_rx );
1263
1264    // desactivates the CMA channel
1265    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
1266
1267    return 0;
1268}  // end _sys_nic_stop()
1269
1270////////////////////////////////////////
1271int _sys_nic_clear( unsigned int is_rx,
1272                    unsigned int channel )
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
1280    if ( nic_channel != channel )
1281    {
1282        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
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;
1309}  // en _sys_nic_clear()
1310
1311////////////////////////////////////////
1312int _sys_nic_stats( unsigned int is_rx,
1313                    unsigned int channel )
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
1321    if ( nic_channel != channel )
1322    {
1323        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
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;
1380}  // end _sys_nic_stats()
1381
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
1412    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
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    {
1421        _set_context_slot( CTX_CMA_FB_ID, channel );
1422        return 0;
1423    }
1424} // end sys_fbf_cma_alloc()
1425
1426
1427////////////////////////
1428int _sys_fbf_cma_init_buf(void*        buf0_vbase, 
1429                          void*        buf1_vbase, 
1430                          void*        sts0_vaddr,
1431                          void*        sts1_vaddr )
1432{
1433#if NB_CMA_CHANNELS > 0
1434
1435    unsigned int       vaddr;           // virtual address
1436    unsigned int       flags;           // for _v2p_translate()
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
1443
1444    // get channel index
1445    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1446
1447    if ( channel >= NB_CMA_CHANNELS )
1448    {
1449        _printf("\n[GIET ERROR] in _fbf_cma_init_buf() : CMA channel index too large\n");
1450        return -1;
1451    }
1452
1453#if GIET_DEBUG_FBF_CMA
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",
1460        channel,
1461        (unsigned int)buf0_vbase,
1462        (unsigned int)buf1_vbase,
1463        (unsigned int)sts0_vaddr,
1464        (unsigned int)sts1_vaddr );
1465#endif
1466
1467    // checking user buffers virtual addresses alignment
1468    if ( ((unsigned int)buf0_vbase & 0x3F) || 
1469         ((unsigned int)buf1_vbase & 0x3F) ) 
1470    {
1471        _printf("\n[GIET ERROR] in _fbf_cma_inti_buf() : user buffer not aligned\n");
1472        return -1;
1473    }
1474
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
1483    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
1484    vaddr = (unsigned int)SEG_FBF_BASE;
1485    fbf_paddr = _v2p_translate( vaddr , &flags );
1486    vaddr = (unsigned int)&_fbf_status[channel];
1487    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
1488
1489    _fbf_chbuf[channel].fbf_desc =
1490        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
1491        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
1492
1493    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
1494    vaddr = (unsigned int)buf0_vbase;
1495    buf0_pbase = _v2p_translate( vaddr , &flags );
1496    if ((flags & PTE_U) == 0) 
1497    {
1498        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf0 not in user space\n");
1499        return -1;
1500    }
1501
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
1514    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
1515    vaddr = (unsigned int)buf1_vbase;
1516    buf1_pbase = _v2p_translate( vaddr , &flags );
1517    if ((flags & PTE_U) == 0) 
1518    {
1519        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf1 not in user space\n");
1520        return -1;
1521    }
1522
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    }
1530
1531    _fbf_chbuf[channel].buf1_desc = 
1532        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
1533        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1534
1535    // Compute and register physical adress of the fbf_chbuf descriptor
1536    vaddr = (unsigned int)&_fbf_chbuf[channel];
1537    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
1538 
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
1593    if ( USE_IOB )
1594    {
1595        // SYNC request for fbf_chbuf descriptor
1596        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
1597    }
1598
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);
1603    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
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
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
1631    volatile unsigned int full = 1;
1632
1633    // get channel index
1634    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1635
1636    if ( channel >= NB_CMA_CHANNELS )
1637    {
1638        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1639                "CMA channel index too large\n");
1640        return -1;
1641    }
1642
1643    // get fbf_chbuf descriptor pointer
1644    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1645
1646#if GIET_DEBUG_FBF_CMA
1647_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
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",
1653        channel , buffer_index,
1654        _fbf_chbuf[channel].buf0_desc,
1655        _fbf_chbuf[channel].buf1_desc,
1656        _fbf_chbuf[channel].fbf_desc );
1657#endif
1658
1659    unsigned long long buf_sts_paddr;
1660    unsigned long long buf_paddr;
1661    unsigned long long fbf_sts_paddr;
1662
1663    if ( buffer_index == 0 )    // user buffer 0
1664    {
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
1668
1669        buf_paddr =
1670            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
1671    }
1672    else                        // user buffer 1
1673    {
1674        buf_sts_paddr =
1675            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
1676            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
1677
1678        buf_paddr =
1679            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
1680    }
1681
1682    fbf_sts_paddr =
1683        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
1684        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
1685
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 );       
1701
1702        full = _physical_read( buf_sts_paddr );
1703    }
1704
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 );
1708
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
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
1736    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
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
1745    _cma_set_register( channel, CHBUF_RUN, 0 );
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{
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);
1779
1780    return 0;
1781}
1782
1783//////////////////////////////////
1784int _sys_task_exit( char* string ) 
1785{
1786    unsigned int date       = _get_proctime();
1787
1788    unsigned int gpid       = _get_procid();
1789    unsigned int cluster_xy = gpid >> P_WIDTH;
1790    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
1791    unsigned int x          = cluster_xy >> Y_WIDTH;
1792    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
1793
1794    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
1795
1796    // print exit message
1797    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
1798            "\n       Cause : %s\n\n",
1799            ltid, x, y, p, date, string );
1800
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 );
1805
1806    // deschedule
1807    _sys_context_switch();
1808
1809    return 0;
1810} 
1811
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   
1909/////////////////////////
1910int _sys_context_switch() 
1911{
1912    unsigned int save_sr;
1913
1914    _it_disable( &save_sr );
1915    _ctx_switch();
1916    _it_restore( &save_sr );
1917
1918    return 0;
1919}
1920
1921////////////////////////
1922int _sys_local_task_id()
1923{
1924    return _get_context_slot(CTX_LTID_ID);
1925}
1926
1927/////////////////////////
1928int _sys_global_task_id()
1929{
1930    return _get_context_slot(CTX_GTID_ID);
1931}
1932
1933////////////////////
1934int _sys_thread_id()
1935{
1936    return _get_context_slot(CTX_TRDID_ID);
1937}
1938
1939////////////////////////////////////////////
1940int _sys_procs_number( unsigned int* x_size,
1941                       unsigned int* y_size,
1942                       unsigned int* nprocs )
1943{
1944    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1945    mapping_cluster_t * cluster = _get_cluster_base(header);
1946
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++ )
1959    {
1960        for ( x = 0 ; x < xmax ; x++ )
1961        {
1962            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
1963        }
1964    }
1965
1966    // check the upper row
1967    for ( x = 0 ; x < xmax ; x++ )
1968    {
1969        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
1970    }
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;
1992}
1993
1994///////////////////////////////////////////////////////
1995int _sys_vseg_get_vbase( char*             vspace_name, 
1996                         char*             vseg_name, 
1997                         unsigned int*     vbase ) 
1998{
1999    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2000    mapping_vspace_t * vspace = _get_vspace_base(header);
2001    mapping_vseg_t * vseg     = _get_vseg_base(header);
2002
2003    unsigned int vspace_id;
2004    unsigned int vseg_id;
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        {
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++) 
2015            {
2016                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
2017                {
2018                    *vbase = vseg[vseg_id].vbase;
2019                    return 0;
2020                }
2021            } 
2022        }
2023    } 
2024    return -1;    // not found
2025}
2026
2027/////////////////////////////////////////////////////////
2028int _sys_vseg_get_length( char*         vspace_name, 
2029                          char*         vseg_name,
2030                          unsigned int* length ) 
2031{
2032    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2033    mapping_vspace_t * vspace = _get_vspace_base(header);
2034    mapping_vseg_t * vseg     = _get_vseg_base(header);
2035
2036    unsigned int vspace_id;
2037    unsigned int vseg_id;
2038
2039    // scan vspaces
2040    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
2041    {
2042        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2043        {
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++) 
2048            {
2049                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
2050                {
2051                    *length = vseg[vseg_id].length;
2052                    return 0;
2053                }
2054            } 
2055        }
2056    } 
2057    return -1;    // not found
2058}
2059
2060////////////////////////////////////////
2061int _sys_xy_from_ptr( void*         ptr,
2062                      unsigned int* x,
2063                      unsigned int* y )
2064{
2065    unsigned int flags;
2066    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
2067   
2068    *x = (paddr>>36) & 0xF;
2069    *y = (paddr>>32) & 0xF;
2070
2071    return 0;
2072}
2073
2074/////////////////////////////////////////
2075int _sys_heap_info( unsigned int* vaddr, 
2076                    unsigned int* length,
2077                    unsigned int  x,
2078                    unsigned int  y ) 
2079{
2080    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
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);
2084
2085    unsigned int task_id;
2086    unsigned int vspace_id;
2087    unsigned int vseg_id = 0xFFFFFFFF;
2088
2089    // searching the heap vseg
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
2096        unsigned int min = vspace[vspace_id].task_offset ;
2097        unsigned int max = min + vspace[vspace_id].tasks ;
2098        for ( task_id = min ; task_id < max ; task_id++ )
2099        {
2100            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
2101            {
2102                vseg_id = task[task_id].heap_vseg_id;
2103                if ( vseg_id != 0xFFFFFFFF ) break;
2104            }
2105        }
2106    }
2107    else                                // searching in the calling task
2108    {
2109        task_id = _get_context_slot(CTX_GTID_ID);
2110        vseg_id = task[task_id].heap_vseg_id;
2111    }
2112
2113    // analysing the vseg_id
2114    if ( vseg_id != 0xFFFFFFFF ) 
2115    {
2116        *vaddr  = vseg[vseg_id].vbase;
2117        *length = vseg[vseg_id].length;
2118        return 0;
2119    }
2120    else 
2121    {
2122        *vaddr  = 0;
2123        *length = 0;
2124        return -1;
2125    }
2126}  // end _sys_heap_info()
2127
2128
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.