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

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

fix kill/exec

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