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

Last change on this file since 696 was 696, checked in by guerin, 9 years ago

kernel: defer task exec to _ctx_switch()

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