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

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

kernel: use non-trivial TTY allocator

Now, TTY channels can be released in non-order. Also fix a few corner
cases with shared allocation.

  • Property svn:executable set to *
File size: 76.9 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[NB_TTY_CHANNELS]  = {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    unsigned int channel;
747
748    if ( _get_context_slot( CTX_TTY_ID ) < NB_TTY_CHANNELS )
749    {
750        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : TTY channel already allocated\n");
751        return 0;
752    }
753
754    // get a new TTY channel
755    for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
756    {
757        if ( !_tty_channel[channel] )
758        {
759            _tty_channel[channel] = 1;
760            break;
761        }
762    }
763    if ( channel >= NB_TTY_CHANNELS )
764    {
765        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : no TTY channel available\n");
766        return -1;
767    }
768
769    // reset kernel buffer for allocated TTY channel
770    _tty_rx_full[channel] = 0;
771
772    // allocate a WTI mailbox to the calling proc if external IRQ
773    unsigned int unused;
774    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &unused ); 
775   
776    // update CTX_TTY_ID
777    if ( shared )         // for all tasks in the same vspace
778    {
779        unsigned int      vspace_id = _get_context_slot( CTX_VSID_ID );
780        mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
781        mapping_vspace_t  *vspace   = _get_vspace_base(header);
782        mapping_task_t    *task     = _get_task_base(header);
783
784        // scan tasks in vspace
785        unsigned int task_id;
786        for (task_id = vspace[vspace_id].task_offset;
787             task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
788             task_id++)
789        {
790            unsigned int y_size        = header->y_size;
791            unsigned int cid           = task[task_id].clusterid;
792            unsigned int x             = cid / y_size;
793            unsigned int y             = cid % y_size;
794            unsigned int p             = task[task_id].proclocid;
795            unsigned int ltid          = task[task_id].ltid;
796            static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
797
798            // don't overwrite TTY_ID
799            if ( psched->context[ltid][CTX_TTY_ID] >= NB_TTY_CHANNELS )
800            {
801                psched->context[ltid][CTX_TTY_ID] = channel;
802            }
803        }
804    }
805    else                  // for calling task only
806    {
807        _set_context_slot( CTX_TTY_ID, channel );
808    }
809
810    return 0;
811}
812
813/////////////////////////////////////////
814// NOTE: not a syscall
815int _sys_tty_release()
816{
817    unsigned int channel = _get_context_slot( CTX_TTY_ID );
818
819    if ( channel == -1 )
820    {
821        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : TTY channel already released\n");
822        return -1;
823    }
824
825    // release WTI mailbox
826    if ( USE_PIC ) _ext_irq_release( ISR_TTY_RX , channel );
827
828    // reset CTX_TTY_ID for all tasks in vspace
829    unsigned int      vspace_id = _get_context_slot( CTX_VSID_ID );
830    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
831    mapping_vspace_t  *vspace   = _get_vspace_base(header);
832    mapping_task_t    *task     = _get_task_base(header);
833
834    unsigned int task_id;
835    for (task_id = vspace[vspace_id].task_offset;
836         task_id < (vspace[vspace_id].task_offset + vspace[vspace_id].tasks);
837         task_id++)
838    {
839        unsigned int y_size        = header->y_size;
840        unsigned int cid           = task[task_id].clusterid;
841        unsigned int x             = cid / y_size;
842        unsigned int y             = cid % y_size;
843        unsigned int p             = task[task_id].proclocid;
844        unsigned int ltid          = task[task_id].ltid;
845        static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
846
847        // only clear matching TTY_ID
848        if ( psched->context[ltid][CTX_TTY_ID] == channel )
849        {
850            psched->context[ltid][CTX_TTY_ID] = -1;
851        }
852    }
853
854    // release TTY channel
855    _tty_channel[channel] = 0;
856
857    return 0;
858}
859
860/////////////////////////////////////////////////
861int _sys_tty_write( const char*  buffer,   
862                    unsigned int length,    // number of characters
863                    unsigned int channel)   // channel index
864{
865    unsigned int  nwritten;
866
867    // compute and check tty channel
868    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
869    if( channel >= NB_TTY_CHANNELS ) return -1;
870
871    // write string to TTY channel
872    for (nwritten = 0; nwritten < length; nwritten++) 
873    {
874        // check tty's status
875        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
876
877        // write one byte
878        if (buffer[nwritten] == '\n') 
879        {
880            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
881        }
882        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
883    }
884   
885    return nwritten;
886}
887
888////////////////////////////////////////////////
889int _sys_tty_read( char*        buffer, 
890                   unsigned int length,    // unused
891                   unsigned int channel)   // channel index
892{
893    // compute and check tty channel
894    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
895    if( channel >= NB_TTY_CHANNELS ) return -1;
896
897    // read one character from TTY channel
898    if (_tty_rx_full[channel] == 0) 
899    {
900        return 0;
901    }
902    else 
903    {
904        *buffer = _tty_rx_buf[channel];
905        _tty_rx_full[channel] = 0;
906        return 1;
907    }
908}
909
910///////////////////////////////////////////
911int _sys_tty_get_lock( unsigned int   channel,       // unused
912                       unsigned int * save_sr_ptr )
913{
914    // check tty channel
915    if( channel != 0 )  return 1;
916
917    _it_disable( save_sr_ptr );
918    _sqt_lock_acquire( &_tty0_sqt_lock );
919    return 0;
920}
921
922///////////////////////////////////////////////
923int _sys_tty_release_lock( unsigned int   channel,
924                           unsigned int * save_sr_ptr )
925{
926    // check tty channel
927    if( channel != 0 )  return 1;
928
929    _sqt_lock_release( &_tty0_sqt_lock );
930    _it_restore( save_sr_ptr );
931    return 0;
932}
933
934//////////////////////////////////////////////////////////////////////////////
935//             TIM related syscall handlers
936//////////////////////////////////////////////////////////////////////////////
937
938////////////////////
939int _sys_tim_alloc()
940{
941    // get a new timer index
942    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
943
944    if ( channel >= NB_TIM_CHANNELS )
945    {
946        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
947        return -1;
948    }
949    else
950    {
951        _set_context_slot( CTX_TIM_ID, channel );
952        return 0;
953    }
954}
955
956////////////////////
957// NOTE: not a syscall
958int _sys_tim_release()
959{
960    // release one timer
961    _atomic_increment( &_tim_channel_allocator, 0xFFFFFFFF );
962
963    return 0;
964}
965
966/////////////////////////////////////////
967int _sys_tim_start( unsigned int period )
968{
969    // get timer index
970    unsigned int channel = _get_context_slot( CTX_TIM_ID );
971    if ( channel >= NB_TIM_CHANNELS )
972    {
973        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
974        return -1;
975    }
976
977    // start timer
978    _timer_start( channel, period );
979
980    return 0;
981}
982
983///////////////////
984int _sys_tim_stop()
985{
986    // get timer index
987    unsigned int channel = _get_context_slot( CTX_TIM_ID );
988    if ( channel >= NB_TIM_CHANNELS )
989    {
990        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
991        return -1;
992    }
993
994    // stop timer
995    _timer_stop( channel );
996
997    return 0;
998}
999
1000//////////////////////////////////////////////////////////////////////////////
1001//             NIC related syscall handlers
1002//////////////////////////////////////////////////////////////////////////////
1003
1004#define NIC_CONTAINER_SIZE 4096
1005
1006////////////////////////////////////////
1007int _sys_nic_alloc( unsigned int is_rx,
1008                    unsigned int xmax,
1009                    unsigned int ymax )
1010{
1011    // check xmax / ymax parameters
1012    if ( xmax > X_SIZE )
1013    {
1014        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
1015        return -1;
1016    }
1017    if ( ymax > Y_SIZE )
1018    {
1019        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
1020        return -1;
1021    }
1022
1023    ////////////////////////////////////////////////////////
1024    // Step 1: get and register CMA and NIC channel index //
1025    ////////////////////////////////////////////////////////
1026
1027    // get a NIC_RX or NIC_TX channel index
1028    unsigned int nic_channel;
1029    unsigned int cma_channel;
1030
1031    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
1032    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
1033
1034    if ( (nic_channel >= NB_NIC_CHANNELS) )
1035    {
1036        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
1037        return -1;
1038    }
1039
1040    // get a CMA channel index
1041    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
1042
1043    if ( cma_channel >= NB_CMA_CHANNELS )
1044    {
1045        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
1046        return -1;
1047    }
1048
1049#if GIET_DEBUG_NIC
1050unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
1051_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
1052        "  nic_channel = %d / cma_channel = %d\n",
1053        thread , _get_proctime() , nic_channel , cma_channel );
1054#endif
1055
1056    // register nic_index and cma_index in task context
1057    if ( is_rx )
1058    {
1059        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
1060        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
1061    }
1062    else
1063    {
1064        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
1065        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
1066    }
1067
1068    /////////////////////////////////////////////////////////////////////////////////
1069    // Step 2: loop on all the clusters                                            //
1070    // Allocate the kernel containers and status, compute the container and the    //
1071    // status physical addresses, fill and synchronize the kernel CHBUF descriptor //
1072    /////////////////////////////////////////////////////////////////////////////////
1073
1074    // physical addresses to be registered in the CMA registers
1075    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
1076    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
1077
1078    // allocate one kernel container and one status variable per cluster in the
1079    // (xmax / ymax) mesh
1080    unsigned int        cx;                 // cluster X coordinate
1081    unsigned int        cy;                 // cluster Y coordinate
1082    unsigned int        index;              // container index in chbuf
1083    unsigned int        vaddr;              // virtual address
1084    unsigned long long  cont_paddr;         // container physical address
1085    unsigned long long  sts_paddr;          // container status physical address
1086
1087    unsigned int        flags;              // for _v2p_translate()
1088
1089    for ( cx = 0 ; cx < xmax ; cx++ )
1090    {
1091        for ( cy = 0 ; cy < ymax ; cy++ )
1092        {
1093            // compute index in chbuf
1094            index = (cx * ymax) + cy; 
1095
1096            // allocate the kernel container
1097            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
1098
1099            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
1100            {
1101                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
1102                        " in cluster[%d,%d]\n", cx, cy );
1103                return -1;
1104            }
1105
1106            // compute container physical address
1107            cont_paddr = _v2p_translate( vaddr , &flags );
1108
1109            // checking container address alignment
1110            if ( cont_paddr & 0x3F )
1111            {
1112                _printf("\n[GIET ERROR] in _sys_nic_alloc() : container address of cluster[%d,%d] not aligned\n",
1113                        cx, cy);
1114                return -1;
1115            }
1116
1117#if GIET_DEBUG_NIC
1118_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
1119        " allocates in cluster[%d,%d]:\n"
1120        " - container vaddr = %x / paddr = %l\n",
1121        thread , cx , cy , vaddr, cont_paddr );
1122#endif
1123
1124            // allocate the kernel container status
1125            // it occupies 64 bytes but only last bit is useful (1 for full and 0 for empty)
1126            vaddr = (unsigned int)_remote_malloc( 64, cx, cy );
1127
1128            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
1129            {
1130                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
1131                        " in cluster[%d,%d]\n", cx, cy );
1132                return -1;
1133            }
1134
1135            // compute status physical address
1136            sts_paddr = _v2p_translate( vaddr , &flags );
1137
1138            // checking status address alignment
1139            if ( sts_paddr & 0x3F )
1140            {
1141                _printf("\n[GIET ERROR] in _sys_nic_alloc() : status address of cluster[%d,%d] not aligned\n",
1142                        cx, cy);
1143                return -1;
1144            }
1145
1146            // initialize chbuf entry
1147            // The buffer descriptor has the following structure:
1148            // - the 26 LSB bits contain bits[6:31] of the buffer physical address
1149            // - the 26 following bits contain bits[6:31] of the physical address where the
1150            //   buffer status is located
1151            // - the 12 MSB bits contain the common address extension of the buffer and its
1152            //   status
1153            if ( is_rx )
1154                _nic_ker_rx_chbuf[nic_channel].buf_desc[index] =
1155                    (unsigned long long)
1156                    ((sts_paddr & 0xFFFFFFFFULL) >> 6) +
1157                    (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26);
1158            else
1159                _nic_ker_tx_chbuf[nic_channel].buf_desc[index] =
1160                    (unsigned long long)
1161                    ((sts_paddr & 0xFFFFFFC0ULL) >> 6) +
1162                    (((cont_paddr & 0xFFFFFFFFFC0ULL) >> 6) << 26);
1163
1164#if GIET_DEBUG_NIC
1165_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
1166        " - status vaddr = %x / paddr = %l\n"
1167        " Buffer descriptor = %l\n",
1168        thread, vaddr, sts_paddr,
1169        (unsigned long long)((sts_paddr & 0xFFFFFFFFULL) >> 6) + 
1170        (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26) );
1171#endif
1172        }
1173    }
1174
1175    // complete kernel chbuf initialisation
1176    if ( is_rx )
1177    {
1178        _nic_ker_rx_chbuf[nic_channel].xmax = xmax;
1179        _nic_ker_rx_chbuf[nic_channel].ymax = ymax;
1180    }
1181    else
1182    {
1183        _nic_ker_tx_chbuf[nic_channel].xmax = xmax;
1184        _nic_ker_tx_chbuf[nic_channel].ymax = ymax;
1185    }
1186
1187    // compute the kernel chbuf descriptor physical address
1188    if ( is_rx ) vaddr = (unsigned int)( &_nic_ker_rx_chbuf[nic_channel] );
1189    else         vaddr = (unsigned int)( &_nic_ker_tx_chbuf[nic_channel] );
1190
1191    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
1192
1193#if GIET_DEBUG_NIC
1194_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
1195        "  vaddr = %x / paddr = %l\n",
1196        thread , vaddr , ker_chbuf_pbase );
1197#endif
1198
1199    // sync the kernel chbuf in L2 after write in L2
1200    _mmc_sync( ker_chbuf_pbase, sizeof( ker_chbuf_t ) );
1201
1202    ///////////////////////////////////////////////////////////////
1203    // Step 3: compute the NIC chbuf descriptor physical address //
1204    ///////////////////////////////////////////////////////////////
1205
1206    unsigned int offset;
1207    if ( is_rx ) offset = 0x4100;
1208    else         offset = 0x4110;
1209    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
1210                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
1211
1212#if GIET_DEBUG_NIC
1213_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
1214        thread , nic_chbuf_pbase );
1215#endif
1216
1217    ////////////////////////////////////////////////////////////////////////////////
1218    // Step 4: initialize CMA registers defining the source & destination chbufs //
1219    ////////////////////////////////////////////////////////////////////////////////
1220
1221    if ( is_rx )               // NIC to kernel
1222    {
1223        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
1224        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
1225        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
1226        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
1227        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
1228        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
1229    }
1230    else                      // kernel to NIC
1231    {
1232        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
1233        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
1234        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
1235        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
1236        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
1237        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
1238    }
1239
1240#if GIET_DEBUG_NIC
1241_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
1242        thread, _get_proctime() );
1243#endif
1244
1245    return nic_channel;
1246} // end _sys_nic_alloc()
1247
1248
1249////////////////////////////////////////
1250// NOTE: not a syscall
1251int _sys_nic_release( unsigned int is_rx )
1252{
1253    if ( is_rx )
1254        _atomic_increment( &_nic_rx_channel_allocator , 0xFFFFFFFF );
1255    else
1256        _atomic_increment( &_nic_tx_channel_allocator , 0xFFFFFFFF );
1257
1258    return 0;
1259}
1260
1261
1262////////////////////////////////////////
1263int _sys_nic_start( unsigned int is_rx,
1264                    unsigned int channel )
1265{
1266    unsigned int nic_channel;
1267    unsigned int cma_channel;
1268
1269    // get NIC channel index and CMA channel index from task context
1270    if ( is_rx )
1271    {
1272        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1273        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
1274    }
1275    else
1276    {
1277        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1278        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1279    }
1280
1281#if GIET_DEBUG_NIC
1282unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
1283_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d\n"
1284        "  get NIC channel = %d / CMA channel = %d\n",
1285        thread, _get_proctime(), nic_channel, cma_channel );
1286#endif
1287
1288    // check NIC and CMA channels index
1289    if ( nic_channel != channel )
1290    {
1291        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
1292        return -1;
1293    }
1294    if ( cma_channel >= NB_CMA_CHANNELS )
1295    {
1296        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
1297        return -1;
1298    }
1299
1300    // start CMA transfer
1301    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
1302    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
1303    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
1304
1305    // activates NIC channel
1306    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 );
1307
1308#if GIET_DEBUG_NIC
1309    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
1310            thread , _get_proctime() );
1311#endif
1312
1313    return 0;
1314}  // end _sys_nic_start()
1315
1316
1317//////////////////////////////////////
1318int _sys_nic_move( unsigned int is_rx,
1319                   unsigned int channel,
1320                   void*        buffer )
1321{
1322
1323#if GIET_DEBUG_NIC
1324unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
1325_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
1326        thread , _get_proctime() );
1327#endif
1328
1329    // check NIC channel index
1330    if ( channel >= NB_NIC_CHANNELS )
1331    {
1332        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
1333        return -1;
1334    }
1335
1336    // get kernel chbuf virtual address
1337    ker_chbuf_t* ker_chbuf;
1338    if ( is_rx )  ker_chbuf = &_nic_ker_rx_chbuf[channel];
1339    else          ker_chbuf = &_nic_ker_tx_chbuf[channel];
1340
1341    // get xmax / ymax parameters
1342    unsigned int xmax = ker_chbuf->xmax;
1343    unsigned int ymax = ker_chbuf->ymax;
1344
1345    // get cluster coordinates for the processor running the calling task
1346    unsigned int  procid = _get_procid();
1347    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
1348    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1349   
1350    // check processor coordinates / (xmax,ymax)
1351    if ( cx >= xmax )
1352    {
1353        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
1354                " / xmax = %d\n", cx , xmax );
1355        return -1;
1356    }
1357    if ( cy >= ymax )
1358    {
1359        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
1360                " / ymax = %d\n", cy , ymax );
1361        return -1;
1362    }
1363   
1364    unsigned long long usr_buf_paddr;       // user buffer physical address
1365    unsigned long long ker_buf_paddr;       // kernel buffer physical address
1366    unsigned long long ker_sts_paddr;       // kernel buffer status physical address
1367    unsigned long long ker_buf_desc;        // kernel buffer descriptor
1368    unsigned int       ker_sts;             // kernel buffer status (full or empty)
1369    unsigned int       index;               // kernel buffer index in chbuf
1370    unsigned int       flags;               // for _v2P_translate
1371
1372    // Compute user buffer physical address and check access rights
1373    usr_buf_paddr = _v2p_translate( (unsigned int)buffer , &flags );
1374
1375    if ( (flags & PTE_U) == 0 )
1376    {
1377        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
1378        return -1;
1379    }
1380
1381#if GIET_DEBUG_NIC
1382_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
1383        thread, usr_buf_paddr );
1384#endif
1385
1386    // compute buffer index, buffer descriptor paddr and buffer status paddr
1387    index = (ymax * cx) + cy;
1388    ker_buf_desc = ker_chbuf->buf_desc[index];
1389    ker_sts_paddr = ((ker_buf_desc & 0xFFF0000000000000ULL) >> 20) +
1390                    ((ker_buf_desc & 0x3FFFFFFULL) << 6);
1391
1392#if GIET_DEBUG_NIC
1393_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_desc %d at cycle %d\n"
1394        "  kernel buffer descriptor = %l\n",
1395        thread, index, _get_proctime(), ker_buf_desc );
1396#endif
1397
1398    // poll local kernel container status until success
1399    while ( 1 )
1400    {
1401        // inval buffer descriptor in L2 before read in L2
1402        _mmc_inval( ker_sts_paddr, 4 );
1403        ker_sts = _physical_read( ker_sts_paddr );
1404
1405#if GIET_DEBUG_NIC
1406_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_sts %d at cycle %d\n"
1407        "  paddr = %l / kernel buffer status = %x\n",
1408        thread, index, _get_proctime(), ker_sts_paddr, ker_sts );
1409#endif
1410
1411        // test buffer status and break if found
1412        if ( ( is_rx != 0 ) && ( ker_sts == 0x1 ) ) break;
1413        if ( ( is_rx == 0 ) && ( ker_sts == 0 ) ) break;
1414    }
1415
1416    // compute kernel buffer physical address
1417    ker_buf_paddr = (ker_buf_desc & 0xFFFFFFFFFC000000ULL) >> 20;
1418   
1419    // move one container
1420    if ( is_rx )              // RX transfer
1421    {
1422        // inval kernel buffer in L2 before read in L2
1423        _mmc_inval( ker_buf_paddr, NIC_CONTAINER_SIZE );
1424
1425        // transfer data from kernel buffer to user buffer
1426        _physical_memcpy( usr_buf_paddr, 
1427                          ker_buf_paddr, 
1428                          NIC_CONTAINER_SIZE );
1429#if GIET_DEBUG_NIC
1430_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
1431        " to user buffer %l at cycle %d\n",
1432        thread , ker_buf_paddr , usr_buf_paddr , _get_proctime() );
1433#endif
1434
1435    }
1436    else                      // TX transfer
1437    {
1438        // transfer data from user buffer to kernel buffer
1439        _physical_memcpy( ker_buf_paddr, 
1440                          usr_buf_paddr, 
1441                          NIC_CONTAINER_SIZE );
1442
1443        // sync kernel buffer in L2 after write in L2
1444        _mmc_sync( ker_buf_paddr, NIC_CONTAINER_SIZE );
1445
1446#if GIET_DEBUG_NIC
1447_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
1448        "user buffer %l to kernel buffer %l at cycle %d\n",
1449        thread , usr_buf_paddr , ker_buf_paddr , _get_proctime() );
1450#endif
1451
1452    }
1453
1454    // update kernel chbuf status
1455    if ( is_rx ) _physical_write ( ker_sts_paddr, 0 );
1456    else         _physical_write ( ker_sts_paddr, 0x1 );
1457
1458    // sync kernel chbuf in L2 after write in L2
1459    _mmc_sync( ker_sts_paddr, 4 );
1460
1461#if GIET_DEBUG_NIC
1462_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
1463        thread , index , _get_proctime() );
1464#endif
1465
1466    return 0;
1467} // end _sys_nic_move()
1468
1469
1470////////////////////////////////////////
1471int _sys_nic_stop( unsigned int is_rx,
1472                   unsigned int channel )
1473{
1474    unsigned int nic_channel;
1475    unsigned int cma_channel;
1476
1477    // get NIC channel index and CMA channel index
1478    if ( is_rx )
1479    {
1480        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1481        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
1482    }
1483    else
1484    {
1485        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1486        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1487    }
1488
1489    // check NIC and CMA channels index
1490    if ( nic_channel != channel )
1491    {
1492        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
1493        return -1;
1494    }
1495    if ( cma_channel >= NB_CMA_CHANNELS )
1496    {
1497        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
1498        return -1;
1499    }
1500
1501    // desactivates the NIC channel
1502    _nic_channel_stop( nic_channel, is_rx );
1503
1504    // desactivates the CMA channel
1505    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
1506
1507    return 0;
1508}  // end _sys_nic_stop()
1509
1510////////////////////////////////////////
1511int _sys_nic_clear( unsigned int is_rx,
1512                    unsigned int channel )
1513{
1514    unsigned int nic_channel;
1515
1516    // get NIC channel
1517    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1518    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1519
1520    if ( nic_channel != channel )
1521    {
1522        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
1523        return -1;
1524    }
1525
1526    if ( is_rx )
1527    {
1528        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
1529        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
1530        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
1531        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
1532        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
1533        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
1534        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
1535        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
1536        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
1537    } 
1538    else
1539    {
1540        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
1541        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
1542        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
1543        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
1544        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
1545        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
1546        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
1547    }
1548    return 0;
1549}  // en _sys_nic_clear()
1550
1551////////////////////////////////////////
1552int _sys_nic_stats( unsigned int is_rx,
1553                    unsigned int channel )
1554{
1555    unsigned int nic_channel;
1556
1557    // get NIC channel
1558    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1559    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1560
1561    if ( nic_channel != channel )
1562    {
1563        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
1564        return -1;
1565    }
1566
1567    if ( is_rx )
1568    {
1569        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
1570        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
1571        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
1572        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
1573        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
1574        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
1575        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
1576        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
1577
1578        _printf("\n### Network Controller RX Statistics ###\n"
1579                "- packets received : %d\n"
1580                "- too small        : %d\n"
1581                "- too big          : %d\n"
1582                "- fifo full        : %d\n" 
1583                "- crc fail         : %d\n" 
1584                "- dst mac fail     : %d\n" 
1585                "- channel full     : %d\n" 
1586                "- broadcast        : %d\n",
1587                received,
1588                too_small,
1589                too_big,
1590                fifo_full,
1591                crc_fail,
1592                dst_fail,
1593                ch_full,
1594                broadcast );
1595    } 
1596    else
1597    {
1598        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
1599        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
1600        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
1601        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
1602        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
1603        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
1604
1605        _printf("\n### Network Controller TX Statistics ###\n"
1606                "- packets received : %d\n"
1607                "- too small        : %d\n"
1608                "- too big          : %d\n"
1609                "- src mac fail     : %d\n" 
1610                "- bypass           : %d\n" 
1611                "- broadcast        : %d\n",
1612                received,
1613                too_big,
1614                too_small,
1615                src_fail,
1616                bypass,
1617                broadcast );
1618    }
1619    return 0;
1620}  // end _sys_nic_stats()
1621
1622/////////////////////////////////////////////////////////////////////////////////////////
1623//    FBF related syscall handlers
1624/////////////////////////////////////////////////////////////////////////////////////////
1625
1626/////////////////////////////////////////////
1627int _sys_fbf_sync_write( unsigned int offset,
1628                         void*        buffer,
1629                         unsigned int length )
1630{
1631    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1632    memcpy( fbf_address, buffer, length);
1633
1634    return 0;
1635}
1636
1637/////////////////////////////////////////////
1638int _sys_fbf_sync_read(  unsigned int offset,
1639                         void*        buffer,
1640                         unsigned int length )
1641{
1642    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1643    memcpy( buffer, fbf_address, length);
1644
1645    return 0;
1646}
1647
1648////////////////////////
1649int _sys_fbf_cma_alloc()
1650{
1651   // get a new CMA channel index
1652    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
1653
1654    if ( channel >= NB_CMA_CHANNELS )
1655    {
1656        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
1657        return -1;
1658    }
1659    else
1660    {
1661        _set_context_slot( CTX_CMA_FB_ID, channel );
1662        return 0;
1663    }
1664} // end sys_fbf_cma_alloc()
1665
1666
1667///////////////////////////////////////////////////
1668int _sys_fbf_cma_init_buf( void*        buf0_vbase, 
1669                           void*        buf1_vbase, 
1670                           void*        sts0_vaddr,
1671                           void*        sts1_vaddr )
1672{
1673#if NB_CMA_CHANNELS > 0
1674
1675    unsigned int       vaddr;           // virtual address
1676    unsigned int       flags;           // for _v2p_translate()
1677    unsigned long long fbf_paddr;       // fbf physical address
1678    unsigned long long fbf_sts_paddr;   // fbf status physical address
1679    unsigned long long buf0_pbase;      // buffer 0 base physical address
1680    unsigned long long sts0_paddr;      // buffer 0 status physical address
1681    unsigned long long buf1_pbase;      // buffer 1 base physical address
1682    unsigned long long sts1_paddr;      // buffer 1 status physical address
1683
1684    // get channel index
1685    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1686
1687    if ( channel >= NB_CMA_CHANNELS )
1688    {
1689        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n");
1690        return -1;
1691    }
1692
1693#if GIET_DEBUG_FBF_CMA
1694_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_init_buf()\n"
1695        " - channel           = %d\n"
1696        " - buf0        vbase = %x\n"
1697        " - buf1        vbase = %x\n"
1698        " - sts0        vaddr = %x\n"
1699        " - sts1        vaddr = %x\n",
1700        channel,
1701        (unsigned int)buf0_vbase,
1702        (unsigned int)buf1_vbase,
1703        (unsigned int)sts0_vaddr,
1704        (unsigned int)sts1_vaddr );
1705#endif
1706
1707    // checking user buffers virtual addresses alignment
1708    if ( ((unsigned int)buf0_vbase & 0x3F) || 
1709         ((unsigned int)buf1_vbase & 0x3F) ) 
1710    {
1711        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n");
1712        return -1;
1713    }
1714
1715    // checking user buffers status virtual addresses alignment
1716    if ( ((unsigned int)sts0_vaddr & 0x3F) ||
1717         ((unsigned int)sts1_vaddr & 0x3F) )
1718    {
1719        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n");
1720        return -1;
1721    }
1722
1723    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
1724    vaddr = (unsigned int)SEG_FBF_BASE;
1725    fbf_paddr = _v2p_translate( vaddr , &flags );
1726    vaddr = (unsigned int)&_fbf_status[channel];
1727    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
1728
1729    _fbf_chbuf[channel].fbf_desc =
1730        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
1731        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
1732
1733    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
1734    vaddr = (unsigned int)buf0_vbase;
1735    buf0_pbase = _v2p_translate( vaddr , &flags );
1736    if ((flags & PTE_U) == 0) 
1737    {
1738        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n");
1739        return -1;
1740    }
1741
1742    vaddr = (unsigned int)sts0_vaddr;
1743    sts0_paddr = _v2p_translate( vaddr , &flags );
1744    if ((flags & PTE_U) == 0) 
1745    {
1746        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n");
1747        return -1;
1748    }
1749
1750    _fbf_chbuf[channel].buf0_desc = 
1751        (unsigned long long) ((sts0_paddr & 0xFFFFFFFFULL) >> 6) +
1752        (((buf0_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1753
1754    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
1755    vaddr = (unsigned int)buf1_vbase;
1756    buf1_pbase = _v2p_translate( vaddr , &flags );
1757    if ((flags & PTE_U) == 0) 
1758    {
1759        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n");
1760        return -1;
1761    }
1762
1763    vaddr = (unsigned int)sts1_vaddr;
1764    sts1_paddr = _v2p_translate( vaddr , &flags );
1765    if ((flags & PTE_U) == 0) 
1766    {
1767        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n");
1768        return -1;
1769    }
1770
1771    _fbf_chbuf[channel].buf1_desc = 
1772        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
1773        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1774
1775    // Compute and register physical adress of the fbf_chbuf descriptor
1776    vaddr = (unsigned int)&_fbf_chbuf[channel];
1777    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
1778 
1779#if GIET_DEBUG_FBF_CMA
1780_printf(" - fbf         pbase = %l\n"
1781        " - fbf status  paddr = %l\n"
1782        " - buf0        pbase = %l\n"
1783        " - buf0 status paddr = %l\n" 
1784        " - buf1        pbase = %l\n"
1785        " - buf0 status paddr = %l\n" 
1786        " - chbuf       pbase = %l\n",
1787        fbf_paddr,
1788        fbf_sts_paddr,
1789        buf0_pbase,
1790        sts0_paddr,
1791        buf1_pbase,
1792        sts1_paddr,
1793        _fbf_chbuf_paddr[channel] );
1794#endif
1795
1796    return 0;
1797
1798#else
1799
1800    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
1801    return -1;
1802
1803#endif 
1804} // end sys_fbf_cma_init_buf()
1805
1806////////////////////////////////////////////
1807int _sys_fbf_cma_start( unsigned int length ) 
1808{
1809#if NB_CMA_CHANNELS > 0
1810
1811    // get channel index
1812    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1813
1814    if ( channel >= NB_CMA_CHANNELS )
1815    {
1816        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
1817        return -1;
1818    }
1819
1820    // check buffers initialization
1821    if ( ( _fbf_chbuf[channel].buf0_desc == 0x0ULL ) &&
1822         ( _fbf_chbuf[channel].buf1_desc == 0x0ULL) &&
1823         ( _fbf_chbuf[channel].fbf_desc == 0x0ULL) )
1824    {
1825        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
1826                "Buffer initialization has not been done\n");
1827        return -1;
1828    }
1829
1830    // initializes buffer length
1831    _fbf_chbuf[channel].length = length;
1832
1833    if ( USE_IOB )
1834    {
1835        // SYNC request for fbf_chbuf descriptor
1836        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
1837    }
1838
1839    // start CMA transfer
1840    unsigned long long paddr = _fbf_chbuf_paddr[channel];
1841    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
1842    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
1843    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
1844    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
1845
1846    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
1847    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
1848    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
1849    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
1850    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
1851    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
1852    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
1853    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
1854    _cma_set_register( channel, CHBUF_RUN      , 1 );
1855
1856    return 0;
1857
1858#else
1859
1860    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1861    return -1;
1862
1863#endif
1864} // end _sys_fbf_cma_start()
1865
1866/////////////////////////////////////////////////////
1867int _sys_fbf_cma_display( unsigned int buffer_index )
1868{
1869#if NB_CMA_CHANNELS > 0
1870
1871    volatile unsigned int full = 1;
1872
1873    // get channel index
1874    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1875
1876    if ( channel >= NB_CMA_CHANNELS )
1877    {
1878        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1879                "CMA channel index too large\n");
1880        return -1;
1881    }
1882
1883    // get fbf_chbuf descriptor pointer
1884    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1885
1886#if GIET_DEBUG_FBF_CMA
1887_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
1888        " - cma channel      = %d\n"
1889        " - buffer index     = %d\n"
1890        " - buf0_desc value  = %l\n"
1891        " - buf1_desc value  = %l\n"
1892        " - fbf_desc  value  = %l\n",
1893        channel , buffer_index,
1894        _fbf_chbuf[channel].buf0_desc,
1895        _fbf_chbuf[channel].buf1_desc,
1896        _fbf_chbuf[channel].fbf_desc );
1897#endif
1898
1899    unsigned long long buf_sts_paddr;
1900    unsigned long long buf_paddr;
1901    unsigned long long fbf_sts_paddr;
1902
1903    if ( buffer_index == 0 )    // user buffer 0
1904    {
1905        buf_sts_paddr =
1906            ((pdesc->buf0_desc & 0xFFF0000000000000ULL) >> 20) + // compute address extension
1907            ((pdesc->buf0_desc & 0x3FFFFFFULL) << 6);            // compute 32 LSB of the address
1908
1909        buf_paddr =
1910            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
1911    }
1912    else                        // user buffer 1
1913    {
1914        buf_sts_paddr =
1915            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
1916            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
1917
1918        buf_paddr =
1919            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
1920    }
1921
1922    fbf_sts_paddr =
1923        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
1924        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
1925
1926#if GIET_DEBUG_FBF_CMA
1927_printf(" - fbf status paddr = %l\n"
1928        " - buf        pbase = %l\n"
1929        " - buf status paddr = %l\n",
1930        fbf_sts_paddr,
1931        buf_paddr,
1932        buf_sts_paddr );
1933#endif
1934       
1935    // waiting user buffer released by the CMA component)
1936    while ( full )
1937    { 
1938        // INVAL L2 cache copy of user buffer status     
1939        // because it has been modified in RAM by the CMA component
1940        _mmc_inval( buf_sts_paddr , 4 );       
1941
1942        full = _physical_read( buf_sts_paddr );
1943    }
1944
1945    // SYNC request for the user buffer, because
1946    // it will be read from XRAM by the CMA component
1947    _mmc_sync( buf_paddr , pdesc->length );
1948
1949    // set user buffer status
1950    _physical_write( buf_sts_paddr, 0x1 );
1951
1952    // reset fbf buffer status
1953    _physical_write( fbf_sts_paddr, 0x0 );
1954   
1955    // SYNC request, because these buffer descriptors
1956    // will be read from XRAM by the CMA component
1957    _mmc_sync( buf_sts_paddr, 4 );
1958    _mmc_sync( fbf_sts_paddr, 4 );
1959
1960    return 0;
1961
1962#else
1963
1964    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1965    return -1;
1966
1967#endif
1968} // end _sys_fbf_cma_display()
1969
1970///////////////////////
1971int _sys_fbf_cma_stop()
1972{
1973#if NB_CMA_CHANNELS > 0
1974
1975    // get channel index
1976    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1977
1978    if ( channel >= NB_CMA_CHANNELS )
1979    {
1980        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
1981        return -1;
1982    }
1983
1984    // Desactivate CMA channel
1985    _cma_set_register( channel, CHBUF_RUN, 0 );
1986
1987    return 0;
1988
1989#else
1990
1991    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
1992    return -1;
1993
1994#endif
1995} // end _sys_fbf_cma_stop()
1996
1997
1998//////////////////////////////////////////////////////////////////////////////
1999//           Miscelaneous syscall handlers
2000//////////////////////////////////////////////////////////////////////////////
2001
2002///////////////
2003int _sys_ukn() 
2004{
2005    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
2006    return -1;
2007}
2008
2009////////////////////////////////////
2010int _sys_proc_xyp( unsigned int* x,
2011                   unsigned int* y,
2012                   unsigned int* p )
2013{
2014    unsigned int gpid = _get_procid();  // global processor index from CPO register
2015
2016    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
2017    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
2018    *p = gpid & ((1<<P_WIDTH)-1);
2019
2020    return 0;
2021}
2022
2023//////////////////////////////////
2024int _sys_task_exit( char* string ) 
2025{
2026    unsigned int date       = _get_proctime();
2027
2028    unsigned int gpid       = _get_procid();
2029    unsigned int cluster_xy = gpid >> P_WIDTH;
2030    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
2031    unsigned int x          = cluster_xy >> Y_WIDTH;
2032    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
2033
2034    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
2035
2036    // print exit message
2037    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
2038            "\n       Cause : %s\n\n",
2039            ltid, x, y, p, date, string );
2040
2041    // set NORUN_MASK_TASK bit (non runnable state)
2042    static_scheduler_t*  psched  = (static_scheduler_t*)_schedulers[x][y][p];
2043    unsigned int*        ptr     = &psched->context[ltid][CTX_NORUN_ID];
2044    _atomic_or( ptr , NORUN_MASK_TASK );
2045
2046    // deschedule
2047    _sys_context_switch();
2048
2049    return 0;
2050} 
2051
2052/////////////////////////
2053int _sys_context_switch() 
2054{
2055    unsigned int save_sr;
2056
2057    _it_disable( &save_sr );
2058    _ctx_switch();
2059    _it_restore( &save_sr );
2060
2061    return 0;
2062}
2063
2064////////////////////////
2065int _sys_local_task_id()
2066{
2067    return _get_context_slot(CTX_LTID_ID);
2068}
2069
2070/////////////////////////
2071int _sys_global_task_id()
2072{
2073    return _get_context_slot(CTX_GTID_ID);
2074}
2075
2076////////////////////
2077int _sys_thread_id()
2078{
2079    return _get_context_slot(CTX_TRDID_ID);
2080}
2081
2082////////////////////////////////////////////
2083int _sys_procs_number( unsigned int* x_size,
2084                       unsigned int* y_size,
2085                       unsigned int* nprocs )
2086{
2087    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2088    mapping_cluster_t * cluster = _get_cluster_base(header);
2089
2090    unsigned int x;
2091    unsigned int y;
2092    unsigned int okmin = 1;
2093    unsigned int okmax = 1;
2094
2095    // compute max values
2096    unsigned int xmax  = header->x_size;
2097    unsigned int ymax  = header->y_size;
2098    unsigned int procs = cluster[0].procs;
2099
2100    // check the (ymax-1) lower rows
2101    for ( y = 0 ; y < ymax-1 ; y++ )
2102    {
2103        for ( x = 0 ; x < xmax ; x++ )
2104        {
2105            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
2106        }
2107    }
2108
2109    // check the upper row
2110    for ( x = 0 ; x < xmax ; x++ )
2111    {
2112        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
2113    }
2114
2115    // return values
2116    if ( okmin && okmax )
2117    {
2118        *x_size = xmax;
2119        *y_size = ymax;
2120        *nprocs = procs;
2121    }
2122    else if ( okmin )
2123    {
2124        *x_size = xmax;
2125        *y_size = ymax-1;
2126        *nprocs = procs;
2127    }
2128    else
2129    {
2130        *x_size = 0;
2131        *y_size = 0;
2132        *nprocs = 0;
2133    }
2134    return 0;
2135}
2136
2137///////////////////////////////////////////////////////
2138int _sys_vseg_get_vbase( char*             vspace_name, 
2139                         char*             vseg_name, 
2140                         unsigned int*     vbase ) 
2141{
2142    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2143    mapping_vspace_t * vspace = _get_vspace_base(header);
2144    mapping_vseg_t * vseg     = _get_vseg_base(header);
2145
2146    unsigned int vspace_id;
2147    unsigned int vseg_id;
2148
2149    // scan vspaces
2150    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
2151    {
2152        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2153        {
2154            // scan vsegs
2155            for (vseg_id = vspace[vspace_id].vseg_offset; 
2156                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
2157                 vseg_id++) 
2158            {
2159                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
2160                {
2161                    *vbase = vseg[vseg_id].vbase;
2162                    return 0;
2163                }
2164            } 
2165        }
2166    } 
2167    return -1;    // not found
2168}
2169
2170/////////////////////////////////////////////////////////
2171int _sys_vseg_get_length( char*         vspace_name, 
2172                          char*         vseg_name,
2173                          unsigned int* length ) 
2174{
2175    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2176    mapping_vspace_t * vspace = _get_vspace_base(header);
2177    mapping_vseg_t * vseg     = _get_vseg_base(header);
2178
2179    unsigned int vspace_id;
2180    unsigned int vseg_id;
2181
2182    // scan vspaces
2183    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
2184    {
2185        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2186        {
2187            // scan vsegs
2188            for (vseg_id = vspace[vspace_id].vseg_offset; 
2189                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
2190                 vseg_id++) 
2191            {
2192                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
2193                {
2194                    *length = vseg[vseg_id].length;
2195                    return 0;
2196                }
2197            } 
2198        }
2199    } 
2200    return -1;    // not found
2201}
2202
2203////////////////////////////////////////
2204int _sys_xy_from_ptr( void*         ptr,
2205                      unsigned int* x,
2206                      unsigned int* y )
2207{
2208    unsigned int flags;
2209    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
2210   
2211    *x = (paddr>>36) & 0xF;
2212    *y = (paddr>>32) & 0xF;
2213
2214    return 0;
2215}
2216
2217/////////////////////////////////////////
2218int _sys_heap_info( unsigned int* vaddr, 
2219                    unsigned int* length,
2220                    unsigned int  x,
2221                    unsigned int  y ) 
2222{
2223    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2224    mapping_task_t *   task    = _get_task_base(header);
2225    mapping_vseg_t *   vseg    = _get_vseg_base(header);
2226    mapping_vspace_t * vspace  = _get_vspace_base(header);
2227
2228    unsigned int task_id;
2229    unsigned int vspace_id;
2230    unsigned int vseg_id = 0xFFFFFFFF;
2231
2232    // searching the heap vseg
2233    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
2234    {
2235        // get vspace global index
2236        vspace_id = _get_context_slot(CTX_VSID_ID);
2237
2238        // scan all tasks in vspace
2239        unsigned int min = vspace[vspace_id].task_offset ;
2240        unsigned int max = min + vspace[vspace_id].tasks ;
2241        for ( task_id = min ; task_id < max ; task_id++ )
2242        {
2243            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
2244            {
2245                vseg_id = task[task_id].heap_vseg_id;
2246                if ( vseg_id != 0xFFFFFFFF ) break;
2247            }
2248        }
2249    }
2250    else                                // searching in the calling task
2251    {
2252        task_id = _get_context_slot(CTX_GTID_ID);
2253        vseg_id = task[task_id].heap_vseg_id;
2254    }
2255
2256    // analysing the vseg_id
2257    if ( vseg_id != 0xFFFFFFFF ) 
2258    {
2259        *vaddr  = vseg[vseg_id].vbase;
2260        *length = vseg[vseg_id].length;
2261        return 0;
2262    }
2263    else 
2264    {
2265        *vaddr  = 0;
2266        *length = 0;
2267        return -1;
2268    }
2269}  // end _sys_heap_info()
2270
2271
2272///////////////////////
2273int _sys_tasks_status()
2274{
2275    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2276    mapping_task_t *    task    = _get_task_base(header);
2277    mapping_vspace_t *  vspace  = _get_vspace_base(header);
2278    mapping_cluster_t * cluster = _get_cluster_base(header);
2279
2280    unsigned int task_id;
2281    unsigned int vspace_id;
2282
2283    // scan all vspaces
2284    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
2285    {
2286        _printf("\n*** vspace %s\n", vspace[vspace_id].name );
2287
2288        // scan all tasks in vspace
2289        unsigned int min = vspace[vspace_id].task_offset ;
2290        unsigned int max = min + vspace[vspace_id].tasks ;
2291        for ( task_id = min ; task_id < max ; task_id++ )
2292        {
2293            unsigned int         clusterid = task[task_id].clusterid;
2294            unsigned int         p         = task[task_id].proclocid;
2295            unsigned int         x         = cluster[clusterid].x;
2296            unsigned int         y         = cluster[clusterid].y;
2297            unsigned int         ltid      = task[task_id].ltid;
2298            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
2299            unsigned int         norun     = psched->context[ltid][CTX_NORUN_ID];
2300            unsigned int         current   = psched->current;
2301
2302            if ( current == ltid )
2303            _printf(" - task %s on P[%d,%d,%d] : running\n", task[task_id].name, x, y, p );
2304            else if ( norun == 0 )
2305            _printf(" - task %s on P[%d,%d,%d] : runable\n", task[task_id].name, x, y, p );
2306            else
2307            _printf(" - task %s on P[%d,%d,%d] : blocked\n", task[task_id].name, x, y, p );
2308        }
2309    }
2310    return 0;
2311}  // end _sys_tasks_status()
2312
2313
2314
2315// Local Variables:
2316// tab-width: 4
2317// c-basic-offset: 4
2318// c-file-offsets:((innamespace . 0)(inline-open . 0))
2319// indent-tabs-mode: nil
2320// End:
2321// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
2322
Note: See TracBrowser for help on using the repository browser.