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

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

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
  • Property svn:executable set to *
File size: 110.1 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(X_SIZE)
29# error: You must define X_SIZE in the hard_config.h file
30#endif
31
32#if !defined(Y_SIZE)
33# error: You must define Y_SIZE in the hard_config.h file
34#endif
35
36#if !defined(NB_PROCS_MAX)
37# error: You must define NB_PROCS_MAX in the hard_config.h file
38#endif
39
40#if !defined(SEG_BOOT_MAPPING_BASE)
41# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
42#endif
43
44#if !defined(NB_TTY_CHANNELS)
45# error: You must define NB_TTY_CHANNELS in the hard_config.h file
46#endif
47
48#if (NB_TTY_CHANNELS < 1)
49# error: NB_TTY_CHANNELS cannot be smaller than 1!
50#endif
51
52#if !defined(NB_TIM_CHANNELS)
53# error: You must define NB_TIM_CHANNELS in the hard_config.h file
54#endif
55
56#if !defined(NB_NIC_CHANNELS)
57# error: You must define NB_NIC_CHANNELS in the hard_config.h file
58#endif
59
60#if !defined(NB_CMA_CHANNELS)
61# error: You must define NB_CMA_CHANNELS in the hard_config.h file
62#endif
63
64#if !defined(GIET_NO_HARD_CC)
65# error: You must define GIET_NO_HARD_CC in the giet_config.h file
66#endif
67
68#if !defined ( GIET_NIC_MAC4 )
69# error: You must define GIET_NIC_MAC4 in the giet_config.h file
70#endif
71
72#if !defined ( GIET_NIC_MAC2 )
73# error: You must define GIET_NIC_MAC2 in the giet_config.h file
74#endif
75
76////////////////////////////////////////////////////////////////////////////
77//        Extern variables
78////////////////////////////////////////////////////////////////////////////
79
80// allocated in tty0.c file.
81extern sqt_lock_t _tty0_sqt_lock;
82
83// allocated in mwr_driver.c file.
84extern simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
85extern unsigned int   _coproc_type[X_SIZE*Y_SIZE];
86extern unsigned int   _coproc_info[X_SIZE*Y_SIZE];
87extern unsigned int   _coproc_mode[X_SIZE*Y_SIZE];
88extern unsigned int   _coproc_error[X_SIZE*Y_SIZE];
89extern unsigned int   _coproc_trdid[X_SIZE*Y_SIZE];
90
91// allocated in tty_driver.c file.
92extern tty_fifo_t   _tty_rx_fifo[NB_TTY_CHANNELS];
93
94// allocated in kernel_init.c file
95extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX]; 
96
97////////////////////////////////////////////////////////////////////////////////
98//     Channel allocators for multi-channels peripherals
99// - The array _***_channel_allocator[channel] defines the number of user
100//   threads for a dynamically allocated channel of peripheral ***.
101// - The array _***_channel_wti[channel] defines the WTI index and the
102//   processor coordinates for the processor receiving the channel WTI.
103////////////////////////////////////////////////////////////////////////////////
104
105#if NB_TTY_CHANNELS
106__attribute__((section(".kdata")))
107unsigned int _tty_channel_alloc[NB_TTY_CHANNELS] = {0};
108
109__attribute__((section(".kdata")))
110unsigned int _tty_channel_wti[NB_TTY_CHANNELS];
111#endif
112
113#if NB_TIM_CHANNELS
114__attribute__((section(".kdata")))
115unsigned int _tim_channel_alloc[NB_TIM_CHANNELS] = {0};
116
117__attribute__((section(".kdata")))
118unsigned int _tim_channel_wti[NB_TIM_CHANNELS];
119#endif
120
121#if NB_CMA_CHANNELS
122__attribute__((section(".kdata")))
123unsigned int _cma_channel_alloc[NB_CMA_CHANNELS] = {0};
124
125__attribute__((section(".kdata")))
126unsigned int _cma_channel_wti[NB_CMA_CHANNELS];
127#endif
128
129#if NB_NIC_CHANNELS
130__attribute__((section(".kdata")))
131unsigned int _nic_rx_channel_alloc[NB_NIC_CHANNELS] = {0};
132
133__attribute__((section(".kdata")))
134unsigned int _nic_rx_channel_wti[NB_NIC_CHANNELS];
135
136__attribute__((section(".kdata")))
137unsigned int _nic_tx_channel_alloc[NB_NIC_CHANNELS] = {0};
138
139__attribute__((section(".kdata")))
140unsigned int _nic_tx_channel_wti[NB_NIC_CHANNELS];
141#endif
142
143////////////////////////////////////////////////////////////////////////////
144//     NIC_RX and NIC_TX kernel chbuf arrays
145////////////////////////////////////////////////////////////////////////////
146
147__attribute__((section(".kdata")))
148ker_chbuf_t  _nic_ker_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
149
150__attribute__((section(".kdata")))
151ker_chbuf_t  _nic_ker_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
152
153////////////////////////////////////////////////////////////////////////////
154// FBF related chbuf descriptors array, indexed by the CMA channel index.
155// Physical addresses of these chbuf descriptors required for L2 cache sync.
156// FBF status
157////////////////////////////////////////////////////////////////////////////
158
159__attribute__((section(".kdata")))
160fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
161
162__attribute__((section(".kdata")))
163unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
164
165__attribute__((section(".kdata")))
166buffer_status_t _fbf_status[NB_CMA_CHANNELS] __attribute__((aligned(64)));
167
168////////////////////////////////////////////////////////////////////////////
169//    Initialize the syscall vector with syscall handlers
170// Note: This array must be synchronised with the define in file stdio.h
171////////////////////////////////////////////////////////////////////////////
172
173__attribute__((section(".kdata")))
174const void * _syscall_vector[64] = 
175{
176    &_sys_proc_xyp,                  /* 0x00 */
177    &_get_proctime,                  /* 0x01 */
178    &_sys_procs_number,              /* 0x02 */
179    &_sys_xy_from_ptr,               /* 0x03 */
180    &_sys_ukn,                       /* 0x04 */
181    &_sys_ukn,                       /* 0x05 */
182    &_sys_ukn,                       /* 0x06 */
183    &_sys_heap_info,                 /* 0x07 */
184    &_sys_vseg_get_vbase,            /* 0x08 */
185    &_sys_vseg_get_length,           /* 0x09 */ 
186    &_sys_fbf_cma_alloc,             /* 0x0A */
187    &_sys_fbf_cma_init_buf,          /* 0x0B */
188    &_sys_fbf_cma_start,             /* 0x0C */
189    &_sys_fbf_cma_display,           /* 0x0D */
190    &_sys_fbf_cma_stop,              /* 0x0E */
191    &_sys_ukn,                       /* 0x0F */
192
193    &_sys_applications_status,       /* 0x10 */
194    &_sys_fbf_sync_write,            /* 0x11 */
195    &_sys_fbf_sync_read,             /* 0x12 */
196    &_sys_ukn,                       /* 0x13 */
197    &_sys_tim_alloc,                 /* 0x14 */
198    &_sys_tim_start,                 /* 0x15 */ 
199    &_sys_tim_stop,                  /* 0x16 */
200    &_sys_kill_application,          /* 0x17 */
201    &_sys_exec_application,          /* 0x18 */   
202    &_sys_ukn,                       /* 0x19 */
203    &_sys_pthread_control,           /* 0x1A */
204    &_sys_pthread_yield,             /* 0x1B */
205    &_sys_pthread_kill,              /* 0x1C */
206    &_sys_pthread_create,            /* 0x1D */
207    &_sys_pthread_join,              /* 0x1E */
208    &_sys_pthread_exit,              /* 0x1F */
209
210    &_fat_open,                      /* 0x20 */
211    &_fat_read,                      /* 0x21 */
212    &_fat_write,                     /* 0x22 */
213    &_fat_lseek,                     /* 0x23 */
214    &_fat_file_info,                 /* 0x24 */
215    &_fat_close,                     /* 0x25 */
216    &_fat_remove,                    /* 0x26 */
217    &_fat_rename,                    /* 0x27 */
218    &_fat_mkdir,                     /* 0x28 */
219    &_fat_opendir,                   /* 0x29 */
220    &_fat_closedir,                  /* 0x2A */
221    &_fat_readdir,                   /* 0x2B */
222    &_sys_ukn,                       /* 0x2C */
223    &_sys_ukn,                       /* 0x2D */
224    &_sys_ukn,                       /* 0x2E */
225    &_sys_ukn,                       /* 0x2F */
226
227    &_sys_nic_alloc,                 /* 0x30 */
228    &_sys_nic_start,                 /* 0x31 */
229    &_sys_nic_move,                  /* 0x32 */
230    &_sys_nic_stop,                  /* 0x33 */
231    &_sys_nic_stats,                 /* 0x34 */
232    &_sys_nic_clear,                 /* 0x35 */ 
233    &_sys_tty_write,                 /* 0x36 */
234    &_sys_tty_read,                  /* 0x37 */
235    &_sys_tty_alloc,                 /* 0x38 */
236    &_sys_ukn,                       /* 0x39 */
237    &_sys_ukn,                       /* 0x3A */
238    &_sys_coproc_completed,          /* 0x3B */
239    &_sys_coproc_alloc,              /* 0x3C */
240    &_sys_coproc_channel_init,       /* 0x3D */
241    &_sys_coproc_run,                /* 0x3E */
242    &_sys_coproc_release,            /* 0x3F */
243};
244
245
246//////////////////////////////////////////////////////////////////////////////
247//           Applications related syscall handlers
248//////////////////////////////////////////////////////////////////////////////
249
250////////////////////////////////////////////////////////////////////////
251// This function is called by the _sys_exec_application function
252// to reload all data segments contained in an application.elf file.
253////////////////////////////////////////////////////////////////////////
254static unsigned int _load_writable_segments( mapping_vspace_t*  vspace )
255{
256
257#if GIET_DEBUG_EXEC 
258unsigned int gpid       = _get_procid();
259unsigned int cluster_xy = gpid >> P_WIDTH;
260unsigned int p          = gpid & ((1<<P_WIDTH)-1);
261unsigned int x          = cluster_xy >> Y_WIDTH;
262unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
263if ( _get_proctime() > GIET_DEBUG_EXEC )
264_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
265        "enters for %s\n", x , y , p , vspace->name );
266#endif
267
268    mapping_header_t*  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
269    mapping_vseg_t*    vseg    = _get_vseg_base(header);
270
271    unsigned int vseg_id;        // vseg index in mapping
272    char         buf[4096];      // buffer to store one cluster
273    unsigned int fd = 0;         // file descriptor
274
275    // first scan on vsegs in vspace to find the .elf pathname
276    for (vseg_id = vspace->vseg_offset;
277         vseg_id < (vspace->vseg_offset + vspace->vsegs);
278         vseg_id++)
279    {
280        if( vseg[vseg_id].type == VSEG_TYPE_ELF )
281        {
282            // open the .elf file associated to vspace
283            fd = _fat_open( vseg[vseg_id].binpath , O_RDONLY );
284            if ( fd < 0 ) return 1;
285            break;
286
287#if GIET_DEBUG_EXEC
288if ( _get_proctime() > GIET_DEBUG_EXEC )
289_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
290        "open %s / fd = %d\n", x , y , p , vseg[vseg_id].binpath , fd );
291#endif
292        }
293    }
294 
295    // load Elf-Header into buffer from .elf file
296    if ( _fat_lseek( fd, 0, SEEK_SET ) < 0 )
297    {
298        _fat_close( fd );
299        return 1;
300    }
301    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
302    {
303        _fat_close( fd );
304        return 1;
305    }
306
307#if GIET_DEBUG_EXEC
308if ( _get_proctime() > GIET_DEBUG_EXEC )
309_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
310        "loaded Elf-Header\n", x , y , p );
311#endif
312
313    // get nsegments and Program-Header-Table offset from Elf-Header
314    Elf32_Ehdr*  elf_header_ptr = (Elf32_Ehdr*)buf;
315    unsigned int offset         = elf_header_ptr->e_phoff;
316    unsigned int nsegments      = elf_header_ptr->e_phnum;
317
318    // load Program-Header-Table from .elf file
319    if ( _fat_lseek( fd, offset, SEEK_SET ) < 0 )
320    {
321        _fat_close( fd );
322        return 1;
323    }
324    if ( _fat_read( fd, (unsigned int)buf, 4096, 0 ) < 0 )
325    {
326        _fat_close( fd );
327        return 1;
328    }
329
330#if GIET_DEBUG_EXEC
331if ( _get_proctime() > GIET_DEBUG_EXEC )
332_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
333        "loaded Program-Header-Table\n", x , y , p );
334#endif
335
336    // set Program-Header-Table pointer
337    Elf32_Phdr*  elf_pht_ptr = (Elf32_Phdr*)buf;
338
339    // second scan on vsegs in vspace to load the seg_data segments :
340    // - type == VSEG_TYPE_ELF
341    // - non eXecutable
342    for (vseg_id = vspace->vseg_offset;
343         vseg_id < (vspace->vseg_offset + vspace->vsegs);
344         vseg_id++)
345    {
346        if( (vseg[vseg_id].type == VSEG_TYPE_ELF) &&   // type ELF
347            ((vseg[vseg_id].mode & 0x4) == 0) )        // non executable
348        {
349            // get vbase and pbase
350            paddr_t      pbase = vseg[vseg_id].pbase; 
351            unsigned int vbase = vseg[vseg_id].vbase;
352
353            // scan segments in Progam-Header-Table to find match
354            // No match checking as the segment was previously found
355            unsigned int seg;
356            for (seg = 0 ; seg < nsegments ; seg++)
357            {
358                if ( (elf_pht_ptr[seg].p_type == PT_LOAD) &&    // loadable
359                     (elf_pht_ptr[seg].p_flags & PF_W)    &&    // writable
360                     (elf_pht_ptr[seg].p_vaddr == vbase) )      // matching
361                {
362                    // Get segment offset and size in .elf file
363                    unsigned int seg_offset = elf_pht_ptr[seg].p_offset;
364                    unsigned int seg_size   = elf_pht_ptr[seg].p_filesz;
365
366                    // compute destination address and extension for _fat_read()
367                    unsigned int dest   = (unsigned int)pbase;
368                    unsigned int extend = (unsigned int)(pbase>>32) | 0xFFFF0000;
369
370                    // load the segment
371                    if ( _fat_lseek( fd, seg_offset, SEEK_SET ) < 0 ) 
372                    {
373                        _fat_close( fd );
374                        return 1;
375                    }
376                    if ( _fat_read( fd, dest, seg_size, extend ) < 0 )
377                    {
378                        _fat_close( fd );
379                        return 1;
380                    }
381                }
382            }
383
384#if GIET_DEBUG_EXEC
385if ( _get_proctime() > GIET_DEBUG_EXEC )
386_printf("\n[DEBUG EXEC] _load_writable_segments() : P[%d,%d,%d] "
387        "loaded segment %x\n", x , y , p , vbase );
388#endif
389        }
390    }  // end loop on writable & loadable segments
391
392    // close .elf file
393    _fat_close( fd );
394
395    return 0;
396}  // end load_writable_segments()
397
398
399
400///////////////////////////////////////
401int _sys_exec_application( char* name )
402{
403    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
404    mapping_vspace_t * vspace  = _get_vspace_base(header);
405    mapping_thread_t * thread  = _get_thread_base(header);
406    mapping_vseg_t   * vseg    = _get_vseg_base(header);
407
408    unsigned int vspace_id;
409    unsigned int thread_id;
410
411#if GIET_DEBUG_EXEC
412unsigned int gpid       = _get_procid();
413unsigned int cluster_xy = gpid >> P_WIDTH;
414unsigned int p          = gpid & ((1<<P_WIDTH)-1);
415unsigned int x          = cluster_xy >> Y_WIDTH;
416unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
417if ( _get_proctime() > GIET_DEBUG_EXEC )
418_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
419        "enters for %s at cycle %d\n", x, y, p, name, _get_proctime() );
420#endif
421
422    unsigned int y_size = header->y_size;
423
424    // scan vspaces to find matching vspace name
425    for (vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++) 
426    {
427        if ( _strcmp( vspace[vspace_id].name, name ) == 0 )  // vspace found
428        {
429
430#if GIET_DEBUG_EXEC
431if ( _get_proctime() > GIET_DEBUG_EXEC )
432_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
433        "found vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
434#endif
435            // reload writable segments
436            if ( _load_writable_segments( &vspace[vspace_id] ) )
437            {
438                _printf("[GIET ERROR] _sys_exec_application() : "
439                        "can't load data segment for vspace %s\n", name );
440                return GIET_SYSCALL_CANNOT_LOAD_DATA_SEGMENT;
441            }
442 
443#if GIET_DEBUG_EXEC
444if ( _get_proctime() > GIET_DEBUG_EXEC )
445_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
446        "load segments for vspace %s at cycle  %d\n", x, y, p, name, _get_proctime() );
447#endif
448            // scan threads in vspace with three goals :
449            // - check all threads desactivated
450            // - re-initialise all threads contexts
451            // - find main thread
452            unsigned int        main_found  = 0;
453            unsigned int        main_ltid   = 0;
454            static_scheduler_t* main_psched = NULL;
455            unsigned int        min         = vspace[vspace_id].thread_offset; 
456            unsigned int        max         = min + vspace[vspace_id].threads; 
457            for ( thread_id = min ; thread_id < max ; thread_id++ ) 
458            {
459                // get thread identifiers : [x,y,p,ltid]
460                unsigned int cid   = thread[thread_id].clusterid;
461                unsigned int x     = cid / y_size;
462                unsigned int y     = cid % y_size;
463                unsigned int p     = thread[thread_id].proclocid;
464                unsigned int ltid  = thread[thread_id].ltid;
465                unsigned int vsid  = thread[thread_id].stack_vseg_id;
466
467                // get scheduler pointer
468                static_scheduler_t* psched = _schedulers[x][y][p];
469
470                // check thread non active
471                if ( psched->context[ltid].slot[CTX_NORUN_ID] == 0 )  // runnable !!!
472                {
473                    _printf("\n[GIET ERROR] in _sys_exec_application() : "
474                            "thread %s already active in vspace %s\n",
475                            thread[thread_id].name, name );
476                    return GIET_SYSCALL_THREAD_ALREADY_ACTIVE;
477                }
478               
479                // initialise thread context
480                unsigned int ctx_epc = psched->context[ltid].slot[CTX_ENTRY_ID];
481                unsigned int ctx_sp  = vseg[vsid].vbase + vseg[vsid].length;
482                unsigned int ctx_ra  = (unsigned int)&_ctx_eret;
483                unsigned int ctx_sr  = GIET_SR_INIT_VALUE;
484
485                psched->context[ltid].slot[CTX_EPC_ID] = ctx_epc;
486                psched->context[ltid].slot[CTX_RA_ID]  = ctx_ra;
487                psched->context[ltid].slot[CTX_SR_ID]  = ctx_sr;
488                psched->context[ltid].slot[CTX_SP_ID]  = ctx_sp;
489
490                // register information required to activate main thread
491                // actual activation done when threads initialisation is completed
492                if ( thread[thread_id].is_main ) 
493                {
494                    main_psched = psched;
495                    main_ltid   = ltid;
496                    main_found  = 1;
497                }
498 
499#if GIET_DEBUG_EXEC
500if ( _get_proctime() > GIET_DEBUG_EXEC )
501_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
502        "initialise thread %s at cycle  %d\n",
503        x, y, p, thread[thread_id].name, _get_proctime() );
504#endif
505            }  // end loop on vspace threads
506
507            // activate main thread
508            if ( main_found )
509            {
510                main_psched->context[main_ltid].slot[CTX_NORUN_ID] = 0;
511            }
512            else
513            {
514                _printf("\n[GIET ERROR] in _sys_exec_application() : "
515                        "main not found in vspace %s\n", name );
516                return GIET_SYSCALL_MAIN_NOT_FOUND;
517            }
518             
519#if GIET_DEBUG_EXEC
520if ( _get_proctime() > GIET_DEBUG_EXEC )
521_printf("\n[DEBUG EXEC] _sys_exec_application() : P[%d,%d,%d] "
522        "lauched %s at cycle %d\n", x, y, p, name, _get_proctime() );
523#endif
524            return GIET_SYSCALL_OK;
525        }
526    }  // end of loop on vspaces
527
528    // vspace not found
529    _printf("\n[GIET ERROR] in _sys_exec_application() : "
530            "vspace %s not found\n", name );
531    return GIET_SYSCALL_VSPACE_NOT_FOUND;
532
533}  // end _sys_exec_application()
534   
535
536///////////////////////////////////////
537int _sys_kill_application( char* name )
538{
539    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
540    mapping_vspace_t * vspace  = _get_vspace_base(header);
541    mapping_thread_t * thread  = _get_thread_base(header);
542
543    unsigned int vspace_id;
544    unsigned int thread_id;
545
546#if GIET_DEBUG_EXEC
547unsigned int gpid       = _get_procid();
548unsigned int cluster_xy = gpid >> P_WIDTH;
549unsigned int p          = gpid & ((1<<P_WIDTH)-1);
550unsigned int x          = cluster_xy >> Y_WIDTH;
551unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
552if ( _get_proctime() > GIET_DEBUG_EXEC )
553_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
554        "enters at cycle %d for %s\n", x, y, p, _get_proctime() , name );
555#endif
556
557    // shell cannot be killed
558    if ( _strcmp( name , "shell" ) == 0 )
559    {
560        _printf("\n[GIET ERROR] in _sys_kill_application() : "
561                "%s application cannot be killed\n", name );
562        return GIET_SYSCALL_APPLI_CANNOT_BE_KILLED;
563    }
564
565    // scan vspaces to find matching vspace name
566    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
567    {
568        if ( _strcmp( vspace[vspace_id].name, name ) == 0 ) 
569        {
570            // scan threads to send KILL signal to all threads in vspace
571            unsigned int y_size = header->y_size;
572            unsigned int min    = vspace[vspace_id].thread_offset; 
573            unsigned int max    = min + vspace[vspace_id].threads; 
574            for ( thread_id = min ; thread_id < max ; thread_id++ ) 
575            {
576                unsigned int cid   = thread[thread_id].clusterid;
577                unsigned int x     = cid / y_size;
578                unsigned int y     = cid % y_size;
579                unsigned int p     = thread[thread_id].proclocid;
580                unsigned int ltid  = thread[thread_id].ltid;
581
582                // get scheduler pointer for processor running the thread
583                static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
584
585                // set KILL signal bit
586                _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
587            } 
588
589#if GIET_DEBUG_EXEC
590if ( _get_proctime() > GIET_DEBUG_EXEC )
591_printf("\n[DEBUG EXEC] _sys_kill_application() P[%d,%d,%d] "
592        "kill %s at cycle %d\n", x, y, p, name, _get_proctime() );
593#endif
594
595            return GIET_SYSCALL_OK;
596        }
597    }  // en loop on vspaces
598
599    _printf("\n[GIET ERROR] in _sys_kill_application() : "
600            "application %s not found\n", name );
601    return GIET_SYSCALL_VSPACE_NOT_FOUND;
602
603}  // end _sys_kill_application()
604   
605
606
607//////////////////////////////
608int _sys_applications_status()
609{
610    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
611    mapping_thread_t *  thread  = _get_thread_base(header);
612    mapping_vspace_t *  vspace  = _get_vspace_base(header);
613    mapping_cluster_t * cluster = _get_cluster_base(header);
614
615    unsigned int thread_id;
616    unsigned int vspace_id;
617
618    // scan all vspaces
619    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
620    {
621        _user_printf("\n*** vspace %s\n", vspace[vspace_id].name );
622
623        // scan all threads in vspace
624        unsigned int min = vspace[vspace_id].thread_offset ;
625        unsigned int max = min + vspace[vspace_id].threads ;
626        for ( thread_id = min ; thread_id < max ; thread_id++ )
627        {
628            unsigned int         clusterid = thread[thread_id].clusterid;
629            unsigned int         p         = thread[thread_id].proclocid;
630            unsigned int         x         = cluster[clusterid].x;
631            unsigned int         y         = cluster[clusterid].y;
632            unsigned int         ltid      = thread[thread_id].ltid;
633            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
634            unsigned int         norun     = psched->context[ltid].slot[CTX_NORUN_ID];
635            unsigned int         tty       = psched->context[ltid].slot[CTX_TTY_ID];
636            unsigned int         current   = psched->current;
637
638            if ( current == ltid )
639            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
640                         "TTY = %d / norun = %x : running\n", 
641                         thread[thread_id].name, x, y, p, ltid, tty, norun );
642            else if ( norun == 0 )
643            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
644                         "TTY = %d / norun = %x : runable\n", 
645                         thread[thread_id].name, x, y, p, ltid, tty, norun);
646            else
647            _user_printf(" - thread %s / P[%d,%d,%d] / ltid = %d / "
648                         "TTY = %d / norun = %x : blocked\n", 
649                         thread[thread_id].name, x, y, p, ltid, tty, norun);
650        }
651    }
652    _user_printf("\n");
653    return GIET_SYSCALL_OK;
654}  // end _sys_applications_status()
655
656
657
658/////////////////////////////////////////////////////////////////////////////
659//          Threads related syscall handlers
660/////////////////////////////////////////////////////////////////////////////
661
662////////////////////////////////////////////////
663int _sys_pthread_create( unsigned int*  buffer,
664                         void*          attr,
665                         void*          function,
666                         void*          arg )
667{
668    // attr argument not supported
669    if ( attr != NULL )
670    {
671        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
672                "attr argument not supported\n" );
673       
674        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
675    }
676
677    // get pointers in mapping
678    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
679    mapping_thread_t*    thread   = _get_thread_base(header);
680    mapping_vspace_t*    vspace   = _get_vspace_base(header);
681    mapping_cluster_t*   cluster  = _get_cluster_base(header);
682
683    // get scheduler for processor running the calling thread
684    static_scheduler_t* psched = (static_scheduler_t*)_get_sched();
685
686    // get calling thread local index in scheduler
687    unsigned int  current = psched->current;
688
689    // get vspace index
690    unsigned int  vspace_id = psched->context[current].slot[CTX_VSID_ID];
691
692#if GIET_DEBUG_EXEC
693if ( _get_proctime() > GIET_DEBUG_EXEC )
694_printf("\n[DEBUG EXEC] _sys_pthread_create() : enters at cycle %d"
695        " for vspace %s / entry = %x\n",
696        _get_proctime() , vspace[vspace_id].name , (unsigned int)function );
697#endif
698
699    unsigned int thread_id;        // searched thread : local index in mapping
700    unsigned int clusterid;        // searched thread : cluster index
701    unsigned int lpid;             // searched thread : processor local index
702    unsigned int ltid;             // searched thread : scheduler thread index
703    unsigned int cx;               // searched thread : X coordinate for searched thread
704    unsigned int cy;               // searched thread : Y coordinate for searched thread
705    unsigned int entry;            // searched thread : entry point
706    unsigned int norun;            // searched thread : norun vector
707    unsigned int trdid;            // searched thread : thread identifier
708
709    // scan threads in vspace to find an inactive thread matching function
710    unsigned int min   = vspace[vspace_id].thread_offset;
711    unsigned int max   = min + vspace[vspace_id].threads;
712    unsigned int found = 0;
713    for ( thread_id = min ; (thread_id < max) && (found == 0) ; thread_id++ )
714    {
715        // get thread coordinates [cx,cy,lpid] and ltid from mapping
716        ltid       = thread[thread_id].ltid;
717        clusterid  = thread[thread_id].clusterid; 
718        lpid       = thread[thread_id].proclocid;
719        cx = cluster[clusterid].x;
720        cy = cluster[clusterid].y;
721
722        // get thread scheduler pointer
723        psched = _schedulers[cx][cy][lpid];
724
725        // get thread entry-point, norun-vector, and trdid from context
726        entry = psched->context[ltid].slot[CTX_ENTRY_ID];
727        norun = psched->context[ltid].slot[CTX_NORUN_ID];
728        trdid = psched->context[ltid].slot[CTX_TRDID_ID];
729
730        // check matching
731        if ( ((unsigned int)function == entry ) && 
732             (norun & NORUN_MASK_THREAD)  ) found = 1;
733
734    }  // end loop on threads
735
736    if ( found )  // one matching inactive thread has been found
737    {
738        // set argument value in thread context
739        if ( arg != NULL ) psched->context[ltid].slot[CTX_A0_ID] = (unsigned int)arg;
740
741        // activate thread
742        psched->context[ltid].slot[CTX_NORUN_ID] = 0;
743
744        // return launched thead global identifier
745        *buffer   = trdid;
746               
747#if GIET_DEBUG_EXEC
748if ( _get_proctime() > GIET_DEBUG_EXEC )
749_printf("\n[DEBUG EXEC] exit _sys_pthread_create() at cycle %d : thread %x launched\n",
750        _get_proctime() , trdid);
751#endif
752        return GIET_SYSCALL_OK;
753    }
754    else         // no matching thread found
755    {
756        _printf("\n[GIET ERROR] in _sys_pthread_create() : "
757                "no matching thread for entry = %x in vspace %s\n",
758                (unsigned int)function , vspace[vspace_id].name );
759       
760        return GIET_SYSCALL_THREAD_NOT_FOUND;
761    }
762
763} // end _sys_pthread_create()
764
765
766///////////////////////////////////////////
767int _sys_pthread_join( unsigned int  trdid,
768                       void*         ptr )
769{
770    // ptr argument not supported
771    if ( ptr != NULL )
772    {
773        _printf("\n[GIET ERROR] in _sys_pthread_join() : "
774                "ptr argument not supported, must be NULL\n" );
775       
776        return GIET_SYSCALL_PTHREAD_ARGUMENT_NOT_SUPPORTED;
777    }
778
779               
780#if GIET_DEBUG_EXEC
781if ( _get_proctime() > GIET_DEBUG_EXEC )
782_printf("\n[DEBUG EXEC] enters _sys_pthread_join() at cycle %d for thread %x\n",
783        _get_proctime() , trdid );
784#endif
785
786    // get calling thread vspace
787    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
788
789    // get and check target thread indexes from trdid
790    unsigned int cx   = (trdid>>24) & 0xFF;
791    unsigned int cy   = (trdid>>16) & 0xFF;
792    unsigned int lpid = (trdid>>8 ) & 0xFF;
793    unsigned int ltid = (trdid    ) & 0xFF;
794
795    // get target thread scheduler, vspace and registered trdid
796    static_scheduler_t*  psched   = _schedulers[cx][cy][lpid];
797    unsigned int target_vspace    = psched->context[ltid].slot[CTX_VSID_ID];
798    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
799
800    // check trdid
801    if ( trdid != registered_trdid )
802    {
803       _printf("\nerror in _sys_pthread_join() : "
804               "trdid = %x / registered_trdid = %x\n",
805               trdid , registered_trdid );
806
807       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
808    }
809   
810    // check calling thread and target thread in same vspace
811    if ( caller_vspace != target_vspace )
812    {
813       _printf("\n[GIET ERROR] in _sys_pthread_join() : "
814               " calling thread and target thread not in same vspace\n");
815
816       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
817    }
818
819    // get target thread state
820    unsigned int* pnorun = &psched->context[ltid].slot[CTX_NORUN_ID];
821
822    asm volatile ( "2000:                      \n"                         
823                   "move  $11,  %0             \n"   /* $11 <= ptr           */
824                   "lw    $11,  0($11)         \n"   /* $11 <= M[ptr]        */
825                   "andi  $11,  $11,    1      \n"   /* $11 <= norun & 0x1   */
826                   "beqz  $11,  2000b          \n"   
827                   :
828                   : "r" (pnorun)
829                   : "$11" );
830
831    return GIET_SYSCALL_OK;
832
833}  // end _sys_pthread_join()
834                       
835
836////////////////////////////////////////
837int _sys_pthread_kill( pthread_t  trdid,
838                       int        signal )
839{
840    // get calling thread vspace
841    unsigned int  caller_vspace = _get_context_slot( CTX_VSID_ID );
842
843    // get and check target thread indexes from trdid
844    unsigned int cx   = (trdid>>24) & 0xFF;
845    unsigned int cy   = (trdid>>16) & 0xFF;
846    unsigned int lpid = (trdid>>8 ) & 0xFF;
847    unsigned int ltid = (trdid    ) & 0xFF;
848
849    // get target thread scheduler, vspace and registered trdid
850    static_scheduler_t*  psched       = _schedulers[cx][cy][lpid];
851    unsigned int target_vspace        = psched->context[ltid].slot[CTX_VSID_ID];
852    unsigned int registered_trdid = psched->context[ltid].slot[CTX_TRDID_ID];
853
854    // check trdid
855    if ( trdid != registered_trdid )
856    {
857       _printf("\n[GIET ERROR] in _sys_pthread_kill() : trdid = %x"
858               " / registered_trdid = %x\n", trdid , registered_trdid );
859       return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
860    }
861   
862    // check calling thread and target thread in same vspace
863    if ( caller_vspace != target_vspace )
864    {
865       _printf("\n[GIET ERROR] in _sys_pthread_kill() : not in same vspace\n");
866       return GIET_SYSCALL_NOT_IN_SAME_VSPACE;
867    }
868
869    // register KILL signal in target thread context if required
870    if ( signal )
871    {
872        _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
873    }
874
875    return GIET_SYSCALL_OK;
876
877}  // end _sys_pthread_kill()
878
879
880/////////////////////////////////////
881int _sys_pthread_exit( void* string ) 
882{
883    unsigned int date       = _get_proctime();
884
885    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
886    mapping_vspace_t * vspace  = _get_vspace_base(header);
887
888    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
889    unsigned int trdid      = _get_context_slot(CTX_TRDID_ID);
890    unsigned int vsid       = _get_context_slot(CTX_VSID_ID);
891
892    // print exit message
893    if ( string == NULL )
894    {
895        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n",
896                trdid , vspace[vsid].name , date );
897    }
898    else
899    {
900        _printf("\n[GIET WARNING] Exit thread %x in vspace %s at cycle %d\n"
901                "               Cause : %s\n\n",
902                trdid , vspace[vsid].name , date , (char*) string );
903    }
904   
905    // get scheduler pointer for calling thread
906    static_scheduler_t*  psched = (static_scheduler_t*)_get_sched();
907
908    // register KILL signal in calling thread context (suicid request)
909    _atomic_or( &psched->context[ltid].slot[CTX_SIGS_ID] , SIGS_MASK_KILL );
910
911    // deschedule calling thread
912    unsigned int save_sr; 
913    _it_disable( &save_sr );
914
915    _ctx_switch();
916
917    return GIET_SYSCALL_OK;
918
919}  // end _sys_pthread_exit()
920
921////////////////////////
922int _sys_pthread_yield() 
923{
924    unsigned int save_sr;
925
926    _it_disable( &save_sr );
927    _ctx_switch();
928    _it_restore( &save_sr );
929
930    return GIET_SYSCALL_OK;
931}
932
933//////////////////////////////////////////////////
934int _sys_pthread_control( unsigned  int  command,
935                          char*     vspace_name,
936                          char*     thread_name )
937{
938
939#if GIET_DEBUG_EXEC
940if ( _get_proctime() > GIET_DEBUG_EXEC )
941_printf("\n[DEBUG EXEC] _sys_pthread_control() at cycle %d : "
942        "enter for vspace %s / thread %s / command = %d\n",
943        _get_proctime() , vspace_name, thread_name, command );
944#endif
945
946    // get pointers in mapping
947    mapping_header_t*    header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
948    mapping_thread_t*    thread   = _get_thread_base(header);
949    mapping_vspace_t*    vspace   = _get_vspace_base(header);
950    mapping_cluster_t*   cluster  = _get_cluster_base(header);
951
952    unsigned int found;
953
954    // search vspace name to get vspace index: vsid
955    found = 0;
956    unsigned int   vsid;
957    for( vsid = 0 ; vsid < header->vspaces ; vsid++ )
958    {
959        if ( _strcmp( vspace[vsid].name, vspace_name ) == 0 )
960        {
961            found = 1;
962            break;
963        }
964    }
965
966    if ( found == 0 ) return GIET_SYSCALL_VSPACE_NOT_FOUND;
967
968    // search thread name in vspace to get thread index: tid
969    found = 0;
970    unsigned int   tid;
971    unsigned int   min = vspace[vsid].thread_offset;
972    unsigned int   max = min + vspace[vsid].threads;
973    for( tid = min ; tid < max ; tid++ )
974    {
975        if ( _strcmp( thread[tid].name, thread_name ) == 0 )
976        {
977            found = 1;
978            break;
979        }
980    }
981
982    if ( found == 0 ) return GIET_SYSCALL_THREAD_NOT_FOUND;
983
984    // get thread coordinates
985    unsigned int cid  = thread[tid].clusterid;
986    unsigned int x    = cluster[cid].x;
987    unsigned int y    = cluster[cid].y;
988    unsigned int p    = thread[tid].proclocid;
989    unsigned int ltid = thread[tid].ltid;
990
991    static_scheduler_t* psched = _schedulers[x][y][p];
992
993    // check trdid and vsid
994    unsigned int trdid = x<<24 | y<<16 | p<<8 | ltid;
995    if ( (psched->context[ltid].slot[CTX_TRDID_ID] != trdid) ||
996         (psched->context[ltid].slot[CTX_VSID_ID]  != vsid) )
997        return GIET_SYSCALL_UNCOHERENT_THREAD_CONTEXT;
998
999    // execute command
1000    if ( command == THREAD_CMD_PAUSE ) 
1001    {
1002        _atomic_or ( &psched->context[ltid].slot[CTX_NORUN_ID],  NORUN_MASK_THREAD );
1003        return GIET_SYSCALL_OK;
1004    }
1005    else if ( command == THREAD_CMD_RESUME )
1006    {
1007        _atomic_and( &psched->context[ltid].slot[CTX_NORUN_ID], ~NORUN_MASK_THREAD );
1008        return GIET_SYSCALL_OK;
1009    }
1010    else if ( command == THREAD_CMD_CONTEXT )
1011    {
1012        _user_printf( " - CTX_TRDID  = %x\n"
1013                      " - CTX_VSID   = %x\n"
1014                      " - CTX_EPC    = %x\n"
1015                      " - CTX_PTAB   = %x\n"
1016                      " - CTX_PTPR   = %x\n"
1017                      " - CTX_SR     = %x\n"
1018                      " - CTX_RA     = %x\n"
1019                      " - CTX_SP     = %x\n"
1020                      " - CTX_ENTRY  = %x\n"
1021                      " - CTX_NORUN  = %x\n"
1022                      " - CTX_SIGS   = %x\n"
1023                      " - CTX_LOCKS  = %x\n"
1024                      " - CTX_TTY    = %x\n"
1025                      " - CTX_NIC_RX = %x\n"
1026                      " - CTX_NIC_TX = %x\n"
1027                      " - CTX_CMA_RX = %x\n"
1028                      " - CTX_CMA_TX = %x\n"
1029                      " - CTX_CMA_FB = %x\n",
1030                      psched->context[ltid].slot[CTX_TRDID_ID], 
1031                      psched->context[ltid].slot[CTX_VSID_ID], 
1032                      psched->context[ltid].slot[CTX_EPC_ID], 
1033                      psched->context[ltid].slot[CTX_PTAB_ID], 
1034                      psched->context[ltid].slot[CTX_PTPR_ID], 
1035                      psched->context[ltid].slot[CTX_SR_ID], 
1036                      psched->context[ltid].slot[CTX_RA_ID], 
1037                      psched->context[ltid].slot[CTX_SP_ID], 
1038                      psched->context[ltid].slot[CTX_ENTRY_ID], 
1039                      psched->context[ltid].slot[CTX_NORUN_ID],
1040                      psched->context[ltid].slot[CTX_SIGS_ID],
1041                      psched->context[ltid].slot[CTX_LOCKS_ID],
1042                      psched->context[ltid].slot[CTX_TTY_ID],
1043                      psched->context[ltid].slot[CTX_NIC_RX_ID],
1044                      psched->context[ltid].slot[CTX_NIC_TX_ID],
1045                      psched->context[ltid].slot[CTX_CMA_RX_ID],
1046                      psched->context[ltid].slot[CTX_CMA_TX_ID],
1047                      psched->context[ltid].slot[CTX_CMA_FB_ID] );
1048        return GIET_SYSCALL_OK;
1049    }
1050    else
1051    {
1052        return GIET_SYSCALL_ILLEGAL_THREAD_COMMAND_TYPE;
1053    }
1054
1055} // end _sys_pthread_control()
1056
1057
1058
1059
1060//////////////////////////////////////////////////////////////////////////////
1061//           Coprocessors related syscall handlers
1062//////////////////////////////////////////////////////////////////////////////
1063
1064//////////////////////////////////////////////////
1065int _sys_coproc_alloc( unsigned int   coproc_type,
1066                       unsigned int*  coproc_info )
1067{
1068    // In this implementation, the allocation policy is constrained:
1069    // the coprocessor must be in the same cluster as the calling thread,
1070    // and there is at most one coprocessor per cluster
1071
1072    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1073    mapping_cluster_t * cluster = _get_cluster_base(header);
1074    mapping_periph_t  * periph  = _get_periph_base(header);
1075
1076    // get cluster coordinates and cluster global index
1077    unsigned int procid     = _get_procid();
1078    unsigned int x          = procid >> (Y_WIDTH + P_WIDTH);
1079    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1080    unsigned int cluster_id = x * Y_SIZE + y;
1081 
1082    // search coprocessor in cluster
1083    mapping_periph_t*  found = NULL;
1084    unsigned int min   = cluster[cluster_id].periph_offset;
1085    unsigned int max   = min + cluster[cluster_id].periphs;
1086    unsigned int periph_id;
1087    for ( periph_id = min ; periph_id < max ; periph_id++ )
1088    {
1089        if ( (periph[periph_id].type == PERIPH_TYPE_MWR) &&
1090             (periph[periph_id].subtype == coproc_type) )
1091        {
1092            found = &periph[periph_id];
1093            break;
1094        }
1095    } 
1096
1097    if ( found != NULL )
1098    {
1099        // get the lock (at most one coproc per cluster)
1100        _simple_lock_acquire( &_coproc_lock[cluster_id] );
1101
1102        // register coproc characteristics in kernel arrays
1103        _coproc_type[cluster_id] = coproc_type;
1104        _coproc_info[cluster_id] = (found->arg0 & 0xFF)     |
1105                                   (found->arg1 & 0xFF)<<8  |
1106                                   (found->arg2 & 0xFF)<<16 |
1107                                   (found->arg3 & 0xFF)<<24 ;
1108
1109        // returns coprocessor info
1110        *coproc_info = _coproc_info[cluster_id];
1111
1112        // register coprocessor coordinates in thread context
1113        unsigned int cluster_xy = (x<<Y_WIDTH) + y;
1114        _set_context_slot( CTX_COPROC_ID , cluster_xy );
1115
1116#if GIET_DEBUG_COPROC
1117_printf("\n[GIET DEBUG COPROC] _sys_coproc_alloc() in cluster[%d,%d]\n"
1118        "  coproc_info = %x / cluster_xy = %x\n",
1119        x , y , *coproc_info , cluster_xy );
1120#endif
1121        return GIET_SYSCALL_OK;
1122    }
1123    else
1124    {
1125         _printf("\n[GIET_ERROR] in _sys_coproc_alloc(): no coprocessor "
1126                 " with type %d available in cluster[%d,%d]\n",
1127                 coproc_type , x , y );
1128        return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
1129    }
1130}  // end _sys_coproc_alloc()
1131
1132////////////////////////////////////////////////////////
1133int _sys_coproc_release( unsigned int coproc_reg_index )
1134{
1135    // processor coordinates
1136    unsigned int procid = _get_procid();
1137    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1138    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1139    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1140   
1141    // get coprocessor coordinates
1142    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1143    if ( cluster_xy > 0xFF )
1144    {
1145         _printf("\n[GIET_ERROR] in _sys_coproc_release(): "
1146                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
1147                 x , y , p ); 
1148         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
1149    }
1150
1151    unsigned int cx         = cluster_xy >> Y_WIDTH;
1152    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
1153    unsigned int cluster_id = cx * Y_SIZE + cy;
1154    unsigned int info       = _coproc_info[cluster_id];
1155    unsigned int nb_to      = info & 0xFF;
1156    unsigned int nb_from    = (info>>8) & 0xFF;
1157    unsigned int channel;
1158
1159    // stops coprocessor and communication channels
1160    _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 0 );
1161    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
1162    {
1163        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 );
1164    }
1165
1166    // deallocates coprocessor coordinates in thread context
1167    _set_context_slot( CTX_COPROC_ID , 0xFFFFFFFF );
1168
1169    // release coprocessor lock
1170    _simple_lock_release( &_coproc_lock[cluster_id] );
1171
1172#if GIET_DEBUG_COPROC
1173_printf("\n[GIET DEBUG COPROC] _sys_coproc_release() in cluster[%d,%d]\n",
1174        cx, cy );
1175#endif
1176
1177    return GIET_SYSCALL_OK;
1178}  // end _sys_coproc_release()
1179
1180//////////////////////////////////////////////////////////////
1181int _sys_coproc_channel_init( unsigned int            channel,
1182                              giet_coproc_channel_t*  desc )
1183{
1184    // processor coordinates
1185    unsigned int procid = _get_procid();
1186    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1187    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1188    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1189   
1190    // get coprocessor coordinates
1191    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1192    if ( cluster_xy > 0xFF )
1193    {
1194         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
1195                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
1196                 x , y , p ); 
1197         return GIET_SYSCALL_COPROCESSOR_NOT_FOUND;
1198    }
1199
1200    // check channel mode
1201    unsigned mode = desc->channel_mode;
1202    if ( (mode != MODE_MWMR) && 
1203         (mode != MODE_DMA_IRQ) && 
1204         (mode != MODE_DMA_NO_IRQ) )
1205    {
1206         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
1207                 " illegal mode\n");
1208         return GIET_SYSCALL_COPROCESSOR_ILLEGAL_MODE;
1209    }
1210
1211    // get memory buffer size
1212    unsigned int size = desc->buffer_size;
1213 
1214    // physical addresses
1215    unsigned long long buffer_paddr;
1216    unsigned int       buffer_lsb;
1217    unsigned int       buffer_msb;
1218    unsigned long long mwmr_paddr = 0;
1219    unsigned int       mwmr_lsb;
1220    unsigned int       mwmr_msb;
1221    unsigned long long lock_paddr = 0;
1222    unsigned int       lock_lsb;
1223    unsigned int       lock_msb;
1224
1225    unsigned int       flags;     // unused
1226
1227    // compute memory buffer physical address
1228    buffer_paddr = _v2p_translate( desc->buffer_vaddr , &flags );
1229    buffer_lsb   = (unsigned int)buffer_paddr;
1230    buffer_msb   = (unsigned int)(buffer_paddr>>32); 
1231
1232    // call MWMR_DMA driver
1233    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MODE, mode ); 
1234    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_SIZE, size ); 
1235    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_LSB, buffer_lsb ); 
1236    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_MSB, buffer_msb ); 
1237                       
1238    if ( mode == MODE_MWMR )
1239    {
1240        // compute MWMR descriptor physical address
1241        mwmr_paddr = _v2p_translate( desc->mwmr_vaddr , &flags );
1242        mwmr_lsb = (unsigned int)mwmr_paddr;
1243        mwmr_msb = (unsigned int)(mwmr_paddr>>32); 
1244
1245        // call MWMR_DMA driver
1246        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_LSB, mwmr_lsb ); 
1247        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_MSB, mwmr_msb ); 
1248
1249        // compute lock physical address
1250        lock_paddr = _v2p_translate( desc->lock_vaddr , &flags );
1251        lock_lsb = (unsigned int)lock_paddr;
1252        lock_msb = (unsigned int)(lock_paddr>>32); 
1253
1254        // call MWMR_DMA driver
1255        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_LSB, lock_lsb ); 
1256        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_MSB, lock_msb ); 
1257    }
1258
1259#if GIET_DEBUG_COPROC
1260_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_init() for coproc[%d,%d]\n"
1261        " channel =  %d / mode = %d / buffer_size = %d\n"
1262        " buffer_paddr = %l / mwmr_paddr = %l / lock_paddr = %l\n",
1263        x , y , channel , mode , size ,
1264        buffer_paddr, mwmr_paddr, lock_paddr );
1265#endif
1266       
1267    return GIET_SYSCALL_OK;
1268} // end _sys_coproc_channel_init()
1269
1270////////////////////////////////////////////////////
1271int _sys_coproc_run( unsigned int coproc_reg_index )
1272{
1273    // processor coordinates
1274    unsigned int procid = _get_procid();
1275    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1276    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1277    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1278   
1279    // get coprocessor coordinates
1280    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1281    if ( cluster_xy > 0xFF )
1282    {
1283         _printf("\n[GIET_ERROR] in _sys_coproc_run(): "
1284                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
1285                 x , y , p ); 
1286         return -1111;
1287    }
1288
1289    unsigned int cx         = cluster_xy >> Y_WIDTH;
1290    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
1291    unsigned int cluster_id = cx * Y_SIZE + cy;
1292    unsigned int info       = _coproc_info[cluster_id];
1293    unsigned int nb_to      = info & 0xFF;
1294    unsigned int nb_from    = (info>>8) & 0xFF;
1295    unsigned int mode       = 0xFFFFFFFF;
1296    unsigned int channel;
1297
1298    // register coprocessor running mode
1299    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
1300    {
1301        unsigned int temp;
1302        temp = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_MODE );
1303
1304        if ( mode == 0xFFFFFFFF ) 
1305        {
1306            mode = temp;
1307        }
1308        else if ( temp != mode )
1309        {
1310            _printf("\n[GIET_ERROR] P[%d,%d,%d] in _sys_coproc_run() for coprocessor[%d,%d]\n"
1311                    "  all channels don't have the same mode\n", x , y , p , cx , cy );
1312            return -1111;
1313        }
1314    }
1315    _coproc_mode[cluster_id] = mode;
1316
1317    // start all communication channels
1318    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
1319    {
1320        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 1 );
1321    }
1322
1323    //////////////////////////////////////////////////////////////////////////
1324    if ( (mode == MODE_MWMR) || (mode == MODE_DMA_NO_IRQ) )  // no descheduling
1325    {
1326        // start coprocessor
1327        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
1328
1329#if GIET_DEBUG_COPROC
1330if ( mode == MODE_MWMR )
1331_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
1332        "   MODE_MWMR at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
1333else
1334_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
1335        "   MODE_DMA_NO_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
1336#endif
1337
1338        return GIET_SYSCALL_OK;
1339    }
1340    ///////////////////////////////////////////////////////////////////////////
1341    else                                // mode == MODE_DMA_IRQ => descheduling
1342    {
1343        // set _coproc_trdid
1344        unsigned int ltid = _get_thread_ltid();
1345        _coproc_trdid[cluster_id] = (x<<24) + (y<<16) + (p<<8) + ltid;
1346
1347        // enters critical section
1348        unsigned int save_sr;
1349        _it_disable( &save_sr ); 
1350
1351        // set NORUN_MASK_COPROC bit
1352        static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
1353        unsigned int*       ptr     = &psched->context[ltid].slot[CTX_NORUN_ID];
1354        _atomic_or( ptr , NORUN_MASK_COPROC );
1355
1356        // start coprocessor
1357        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
1358
1359#if GIET_DEBUG_COPROC
1360_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
1361        "   MODE_DMA_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
1362#endif
1363
1364        // deschedule thread
1365        _ctx_switch(); 
1366
1367#if GIET_DEBUG_COPROC
1368_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] resume\n"
1369        "  coprocessor[%d,%d] completion at cycle %d\n", 
1370        x , y , p , cx , cy , _get_proctime() );
1371#endif
1372
1373        // restore SR
1374        _it_restore( &save_sr );
1375
1376        // return error computed by mwr_isr()
1377        return _coproc_error[cluster_id];
1378    } 
1379} // end _sys_coproc_run()
1380
1381///////////////////////////
1382int _sys_coproc_completed()
1383{
1384    // processor coordinates
1385    unsigned int procid = _get_procid();
1386    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1387    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1388    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1389   
1390    // get coprocessor coordinates
1391    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
1392    if ( cluster_xy > 0xFF )
1393    {
1394         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
1395                 "no coprocessor allocated to thread running on P[%d,%d,%d]\n",
1396                 x , y , p ); 
1397         return -1111;
1398    }
1399
1400    unsigned int cx         = cluster_xy >> Y_WIDTH;
1401    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
1402    unsigned int cluster_id = cx * Y_SIZE + cy;
1403    unsigned int mode       = _coproc_mode[cluster_id];
1404
1405    // analyse possible errors
1406    if ( mode == MODE_DMA_NO_IRQ )
1407    {
1408        unsigned int info       = _coproc_info[cluster_id];
1409        unsigned int nb_to      = info & 0xFF;
1410        unsigned int nb_from    = (info>>8) & 0xFF;
1411        unsigned int error      = 0;
1412        unsigned int channel;
1413        unsigned int status;
1414
1415        // get status for all channels, and signal all reported errors
1416        for ( channel = 0 ; channel < (nb_to +nb_from) ; channel++ )
1417        {
1418            do
1419            {
1420                status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
1421                if ( status == MWR_CHANNEL_ERROR_DATA )
1422                {
1423                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
1424                            " / channel %d / DATA_ERROR\n", channel );
1425                    error = 1;
1426                    break;
1427                }
1428                else if ( status == MWR_CHANNEL_ERROR_LOCK )
1429                {
1430                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
1431                            " / channel %d / LOCK_ERROR\n", channel );
1432                    error = 1;
1433                    break;
1434                }
1435                else if ( status == MWR_CHANNEL_ERROR_DESC )
1436                {
1437                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
1438                            " / channel %d / DESC_ERROR\n", channel );
1439                    error = 1;
1440                    break;
1441                }
1442            } while ( status == MWR_CHANNEL_BUSY );
1443
1444            // reset channel
1445            _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 ); 
1446
1447        }  // end for channels
1448
1449#if GIET_DEBUG_COPROC
1450_printf("\n[GIET DEBUG COPROC] _sys_coproc_completed() for coprocessor[%d,%d] error = %d\n", 
1451        cx , cy , error );
1452#endif
1453
1454        return error;
1455    }
1456    else  // mode == MODE_MWMR or MODE_DMA_IRQ
1457    {
1458        _printf("\n[GIET ERROR] sys_coproc_completed() should not be called for "
1459                "coprocessor[%d,%d] running in MODE_MWMR or MODE_DMA_IRQ\n", cx , cy );
1460        return 1;
1461    }
1462} // end _sys_coproc_completed()
1463
1464
1465//////////////////////////////////////////////////////////////////////////////
1466//             TTY related syscall handlers
1467//////////////////////////////////////////////////////////////////////////////
1468
1469/////////////////////////////////////////
1470int _sys_tty_alloc( unsigned int shared )
1471{
1472    unsigned int channel;    // allocated TTY channel
1473
1474    // get trdid and vsid for the calling thread
1475    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
1476    unsigned int trdid = _get_thread_trdid();
1477
1478    // check no TTY already allocated to calling thread
1479    if ( _get_context_slot( CTX_TTY_ID ) < NB_TTY_CHANNELS )
1480    {
1481        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
1482                "TTY channel already allocated to thread %x\n", trdid );
1483        return -1111;
1484    }
1485
1486    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1487    mapping_vspace_t  *vspace   = _get_vspace_base(header);
1488    mapping_thread_t  *thread   = _get_thread_base(header);
1489   
1490    // compute number of users
1491    unsigned int users;
1492    if ( shared )  users = vspace[vsid].threads;
1493    else           users = 1;
1494
1495    // get a TTY channel
1496    for ( channel = 0 ; channel < NB_TTY_CHANNELS ; channel++ )
1497    {
1498        unsigned int* palloc  = &_tty_channel_alloc[channel];
1499
1500        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
1501    }
1502    if ( channel >= NB_TTY_CHANNELS )
1503    {
1504        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : "
1505                "no TTY channel available for thread %x\n", trdid );
1506        return -1111;
1507    }
1508
1509    // initialise allocated TTY channel
1510    _tty_init( channel );
1511
1512    // allocate a WTI mailbox to the calling proc if external IRQ
1513    unsigned int wti_id;
1514    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &wti_id ); 
1515
1516    // register wti_id and coordinates for processor receiving WTI
1517    unsigned int procid = _get_procid();
1518    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1519    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1520    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1521    _tty_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
1522   
1523    // update CTX_TTY_ID
1524    if ( shared )         // for all threads in vspace
1525    {
1526        // scan threads in vspace
1527        unsigned int tid;
1528        for (tid = vspace[vsid].thread_offset;
1529             tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
1530             tid++)
1531        {
1532            unsigned int y_size        = header->y_size;
1533            unsigned int cid           = thread[tid].clusterid;
1534            unsigned int x             = cid / y_size;
1535            unsigned int y             = cid % y_size;
1536            unsigned int p             = thread[tid].proclocid;
1537            unsigned int ltid          = thread[tid].ltid;
1538            static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
1539
1540            psched->context[ltid].slot[CTX_TTY_ID] = channel;
1541        }
1542    }
1543    else                  // for calling thread only
1544    {
1545        _set_context_slot( CTX_TTY_ID, channel );
1546    }
1547
1548    return GIET_SYSCALL_OK;
1549}  // end _sys_tty_alloc()
1550
1551//////////////////////
1552int _sys_tty_release()     // NOTE: not a syscall
1553{
1554    unsigned int channel = _get_context_slot( CTX_TTY_ID );
1555
1556    if ( channel == -1 )
1557    {
1558        unsigned int trdid = _get_thread_trdid();
1559        _printf("\n[GIET_ERROR] in _sys_tty_release() : "
1560                "TTY channel already released for thread %x\n", trdid );
1561        return -1111;
1562    }
1563
1564    // reset CTX_TTY_ID for the calling thread
1565    _set_context_slot( CTX_TTY_ID , 0xFFFFFFFF );
1566
1567    // atomically decrement the _tty_channel_allocator[] array
1568    _atomic_increment( &_tty_channel_alloc[channel] , -1 );
1569
1570    // release WTI mailbox if TTY channel no more used
1571    if ( USE_PIC  && (_tty_channel_alloc[channel] == 0) ) 
1572    {
1573        _ext_irq_release( ISR_TTY_RX , channel );
1574    }
1575
1576    return GIET_SYSCALL_OK;
1577}  // end sys_tty_release()
1578
1579////////////////////////////////////////
1580int _sys_tty_write( const char*  buffer,   
1581                    unsigned int length,    // number of characters
1582                    unsigned int channel)   // channel index
1583{
1584    unsigned int  nwritten;
1585
1586    // compute and check tty channel
1587    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
1588    if( channel >= NB_TTY_CHANNELS ) return -1111;
1589
1590    // write string to TTY channel
1591    for (nwritten = 0; nwritten < length; nwritten++) 
1592    {
1593        // check tty's status
1594        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
1595
1596        // write one byte
1597        if (buffer[nwritten] == '\n') 
1598        {
1599            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
1600        }
1601        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
1602    }
1603   
1604    return nwritten;
1605}
1606
1607///////////////////////////////////////
1608int _sys_tty_read( char*        buffer, 
1609                   unsigned int length,    // unused
1610                   unsigned int channel)   // channel index
1611{
1612    // compute and check tty channel
1613    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
1614    if( channel >= NB_TTY_CHANNELS ) return -1111;
1615
1616    unsigned int save_sr;
1617    unsigned int found = 0;
1618
1619    // get pointer on TTY_RX FIFO
1620    tty_fifo_t*  fifo = &_tty_rx_fifo[channel];
1621
1622    // try to read one character from FIFO
1623    // blocked in while loop until success
1624    while ( found == 0 )
1625    {
1626        if ( fifo->sts == 0)   // FIFO empty => deschedule
1627        {
1628            // enters critical section
1629             _it_disable( &save_sr );
1630
1631            // set NORUN_MASK_TTY bit for calling thread
1632            static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
1633            unsigned int ltid = psched->current;
1634            _atomic_or( &psched->context[ltid].slot[CTX_NORUN_ID] , NORUN_MASK_TTY );
1635
1636            // register descheduling thread trdid
1637            fifo->trdid = _get_thread_trdid();
1638
1639             // deschedule calling thread
1640            _ctx_switch();
1641
1642            // exit critical section
1643            _it_restore( &save_sr );
1644        }
1645        else                             // FIFO not empty => get one character
1646        {
1647            *buffer   = fifo->data[fifo->ptr];
1648            fifo->sts = fifo->sts - 1;
1649            fifo->ptr = (fifo->ptr + 1) % TTY_FIFO_DEPTH;
1650            found     = 1;
1651        }
1652    }
1653
1654    return 1;
1655}
1656
1657
1658
1659//////////////////////////////////////////////////////////////////////////////
1660//             TIMER related syscall handlers
1661//////////////////////////////////////////////////////////////////////////////
1662
1663////////////////////
1664int _sys_tim_alloc()
1665{
1666
1667#if NB_TIM_CHANNELS
1668
1669    unsigned int channel;    // allocated TIMER channel
1670
1671    unsigned int trdid = _get_thread_trdid();
1672
1673    // check no TIMER already allocated to calling thread
1674    if ( _get_context_slot( CTX_TIM_ID ) < NB_TIM_CHANNELS )
1675    {
1676        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
1677                "TIMER channel already allocated to thread %x\n", trdid );
1678        return -1111;
1679    }
1680
1681    // get a TIMER channel
1682    for ( channel = 0 ; channel < NB_TIM_CHANNELS ; channel++ )
1683    {
1684        unsigned int* palloc  = &_tim_channel_alloc[channel];
1685
1686        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
1687    }
1688    if ( channel >= NB_TIM_CHANNELS )
1689    {
1690        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : "
1691                "no TIMER channel available for thread %x\n", trdid );
1692        return -1111;
1693    }
1694
1695    // allocate a WTI mailbox to the calling proc if external IRQ
1696    unsigned int wti_id;
1697    if ( USE_PIC ) _ext_irq_alloc( ISR_TIMER , channel , &wti_id ); 
1698
1699    // register wti_id and coordinates for processor receiving WTI
1700    unsigned int procid = _get_procid();
1701    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
1702    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1703    unsigned int p      = procid & ((1<<P_WIDTH)-1);
1704    _tim_channel_wti[channel] = x<<24 | y<<16 | p<<8 | wti_id;
1705   
1706    // update CTX_TIM_ID in thread context
1707    _set_context_slot( CTX_TIM_ID, channel );
1708
1709    return GIET_SYSCALL_OK;
1710
1711#else
1712
1713    _printf("\n[GIET ERROR] in _sys_tim_alloc() : NB_TIM_CHANNELS = 0\n");
1714    return -1111;
1715
1716#endif
1717}  // end _sys_tim_alloc()
1718
1719
1720//////////////////////
1721int _sys_tim_release()     // NOTE: not a syscall
1722{
1723
1724#if NB_TIM_CHANNELS
1725
1726    unsigned int channel = _get_context_slot( CTX_TIM_ID );
1727
1728    if ( channel == -1 )
1729    {
1730        unsigned int trdid = _get_thread_trdid();
1731        _printf("\n[GIET_ERROR] in _sys_tim_release() : "
1732                "TIMER channel already released for thread %x\n", trdid );
1733        return -1111;
1734    }
1735
1736    // reset CTX_TIM_ID for the calling thread
1737    _set_context_slot( CTX_TIM_ID , 0xFFFFFFFF );
1738
1739    // reset the _tim_channel_alloc[] array
1740    _tim_channel_alloc[channel] = 0;
1741
1742    // release WTI mailbox if TTY channel no more used
1743    if ( USE_PIC ) 
1744    {
1745        _ext_irq_release( PERIPH_TYPE_TIM , channel );
1746    }
1747
1748    return GIET_SYSCALL_OK;
1749
1750#else
1751
1752    _printf("\n[GIET ERROR] in _sys_tim_release() : NB_TIM_CHANNELS = 0\n");
1753    return -1111;
1754
1755#endif
1756}  // end _sys_tim_release()
1757
1758/////////////////////////////////////////
1759int _sys_tim_start( unsigned int period )
1760{
1761
1762#if NB_TIM_CHANNELS
1763
1764    // get timer index
1765    unsigned int channel = _get_context_slot( CTX_TIM_ID );
1766    if ( channel >= NB_TIM_CHANNELS )
1767    {
1768        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
1769        return -1111;
1770    }
1771
1772    // start timer
1773    _timer_start( channel, period );
1774
1775    return GIET_SYSCALL_OK;
1776
1777#else
1778
1779    _printf("\n[GIET ERROR] in _sys_tim_start() : NB_TIM_CHANNELS = 0\n");
1780    return -1111;
1781
1782#endif
1783}
1784
1785///////////////////
1786int _sys_tim_stop()
1787{
1788
1789#if NB_TIM_CHANNELS
1790
1791    // get timer index
1792    unsigned int channel = _get_context_slot( CTX_TIM_ID );
1793    if ( channel >= NB_TIM_CHANNELS )
1794    {
1795        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
1796        return -1111;
1797    }
1798
1799    // stop timer
1800    _timer_stop( channel );
1801
1802    return GIET_SYSCALL_OK;
1803
1804#else
1805
1806    _printf("\n[GIET ERROR] in _sys_tim_stop() : NB_TIM_CHANNELS = 0\n");
1807    return -1111;
1808
1809#endif
1810}
1811
1812
1813//////////////////////////////////////////////////////////////////////////////
1814//             NIC related syscall handlers
1815//////////////////////////////////////////////////////////////////////////////
1816
1817#define NIC_CONTAINER_SIZE 4096
1818
1819#if NB_NIC_CHANNELS
1820
1821////////////////////////////////////////
1822int _sys_nic_alloc( unsigned int is_rx,
1823                    unsigned int xmax,
1824                    unsigned int ymax )
1825{
1826    mapping_header_t  *header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1827    mapping_vspace_t  *vspace   = _get_vspace_base(header);
1828    mapping_thread_t  *thread   = _get_thread_base(header);
1829
1830    // get calling thread trdid, vspace index, and number of threads
1831    unsigned int trdid = _get_thread_trdid();
1832    unsigned int vsid  = _get_context_slot( CTX_VSID_ID );
1833    unsigned int users = vspace[vsid].threads;
1834
1835    // check xmax / ymax parameters
1836    if ( (xmax > X_SIZE) || (ymax > Y_SIZE) )
1837    {
1838        _printf("\n[GIET_ERROR] in _sys_nic_alloc() "
1839                "xmax or ymax argument too large for thread %x\n", trdid );
1840        return -1111;
1841    }
1842
1843    ////////////////////////////////////////////////////////
1844    // Step 1: get and register CMA and NIC channel index //
1845    ////////////////////////////////////////////////////////
1846
1847    unsigned int   nic_channel;
1848    unsigned int   cma_channel;
1849    unsigned int*  palloc;
1850
1851    // get a NIC_RX or NIC_TX channel
1852    for ( nic_channel = 0 ; nic_channel < NB_NIC_CHANNELS ; nic_channel++ )
1853    {
1854        if ( is_rx ) palloc = &_nic_rx_channel_alloc[nic_channel];
1855        else         palloc = &_nic_tx_channel_alloc[nic_channel];
1856
1857        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
1858    }
1859    if ( (nic_channel >= NB_NIC_CHANNELS) )
1860    {
1861        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1862                "no NIC channel available for thread %x\n", trdid );
1863        return -1111;
1864    }
1865
1866    // get a CMA channel
1867    for ( cma_channel = 0 ; cma_channel < NB_CMA_CHANNELS ; cma_channel++ )
1868    {
1869        palloc = &_cma_channel_alloc[cma_channel];
1870
1871        if ( _atomic_test_and_set( palloc , users ) == 0 ) break;
1872    }
1873    if ( cma_channel >= NB_CMA_CHANNELS )
1874    {
1875        _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1876                "no CMA channel available for thread %x\n", trdid );
1877        if ( is_rx )  _nic_rx_channel_alloc[nic_channel] = 0;
1878        else          _nic_tx_channel_alloc[nic_channel] = 0;
1879        return -1111;
1880    }
1881
1882#if GIET_DEBUG_NIC
1883_printf("\n[GIET DEBUG NIC] Thread %d enters sys_nic_alloc() at cycle %d\n"
1884        "  nic_channel = %d / cma_channel = %d\n",
1885        trdid , _get_proctime() , nic_channel , cma_channel );
1886#endif
1887
1888    // register nic_index and cma_index in all threads
1889    // contexts that are in the same vspace
1890    unsigned int tid;
1891    for (tid = vspace[vsid].thread_offset;
1892         tid < (vspace[vsid].thread_offset + vspace[vsid].threads);
1893         tid++)
1894    {
1895        unsigned int y_size        = header->y_size;
1896        unsigned int cid           = thread[tid].clusterid;
1897        unsigned int x             = cid / y_size;
1898        unsigned int y             = cid % y_size;
1899        unsigned int p             = thread[tid].proclocid;
1900        unsigned int ltid          = thread[tid].ltid;
1901        static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p];
1902
1903        if ( is_rx )
1904        {
1905            if ( (psched->context[ltid].slot[CTX_NIC_RX_ID] < NB_NIC_CHANNELS) ||
1906                 (psched->context[ltid].slot[CTX_CMA_RX_ID] < NB_CMA_CHANNELS) )
1907            {
1908                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1909                        "NIC_RX or CMA_RX channel already allocated for thread %x\n", trdid );
1910                _nic_rx_channel_alloc[nic_channel] = 0;
1911                _cma_channel_alloc[cma_channel]    = 0;
1912                return -1111;
1913            }
1914            else
1915            {
1916                psched->context[ltid].slot[CTX_NIC_RX_ID] = nic_channel;
1917                psched->context[ltid].slot[CTX_CMA_RX_ID] = cma_channel;
1918            }
1919        }
1920        else // is_tx
1921        {
1922            if ( (psched->context[ltid].slot[CTX_NIC_TX_ID] < NB_NIC_CHANNELS) ||
1923                 (psched->context[ltid].slot[CTX_CMA_TX_ID] < NB_CMA_CHANNELS) )
1924            {
1925                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1926                        "NIC_TX or CMA_TX channel already allocated for thread %x\n", trdid );
1927                _nic_tx_channel_alloc[nic_channel] = 0;
1928                _cma_channel_alloc[cma_channel]    = 0;
1929                return -1111;
1930            }
1931            else
1932            {
1933                psched->context[ltid].slot[CTX_NIC_TX_ID] = nic_channel;
1934                psched->context[ltid].slot[CTX_CMA_TX_ID] = cma_channel;
1935            }
1936        }
1937    }  // end loop on threads
1938
1939    /////////////////////////////////////////////////////////////////////////////////
1940    // Step 2: loop on all the clusters                                            //
1941    // Allocate the kernel containers and status, compute the container and the    //
1942    // status physical addresses, fill and synchronize the kernel CHBUF descriptor //
1943    /////////////////////////////////////////////////////////////////////////////////
1944
1945    // physical addresses to be registered in the CMA registers
1946    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
1947    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
1948
1949    // allocate one kernel container and one status variable per cluster in the
1950    // (xmax / ymax) mesh
1951    unsigned int        cx;                 // cluster X coordinate
1952    unsigned int        cy;                 // cluster Y coordinate
1953    unsigned int        index;              // container index in chbuf
1954    unsigned int        vaddr;              // virtual address
1955    unsigned long long  cont_paddr;         // container physical address
1956    unsigned long long  sts_paddr;          // container status physical address
1957
1958    unsigned int        flags;              // for _v2p_translate()
1959
1960    for ( cx = 0 ; cx < xmax ; cx++ )
1961    {
1962        for ( cy = 0 ; cy < ymax ; cy++ )
1963        {
1964            // compute index in chbuf
1965            index = (cx * ymax) + cy; 
1966
1967            // allocate the kernel container
1968            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
1969
1970            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
1971            {
1972                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
1973                        "not enough kenel heap in cluster[%d,%d]\n", cx, cy );
1974                return -1111;
1975            }
1976
1977            // compute container physical address
1978            cont_paddr = _v2p_translate( vaddr , &flags );
1979
1980            // checking container address alignment
1981            if ( cont_paddr & 0x3F )
1982            {
1983                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
1984                        "container address of cluster[%d,%d] not aligned\n", cx, cy);
1985                return -1111;
1986            }
1987
1988#if GIET_DEBUG_NIC
1989_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
1990        " allocates in cluster[%d,%d]:\n"
1991        " - container vaddr = %x / paddr = %l\n",
1992        thread , cx , cy , vaddr, cont_paddr );
1993#endif
1994
1995            // allocate the kernel container status
1996            // it occupies 64 bytes but only last bit is useful (1 for full and 0 for empty)
1997            vaddr = (unsigned int)_remote_malloc( 64, cx, cy );
1998
1999            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
2000            {
2001                _printf("\n[GIET_ERROR] in _sys_nic_alloc() : "
2002                        "not enough kernel heap in cluster[%d,%d]\n", cx, cy );
2003                return -1111;
2004            }
2005
2006            // compute status physical address
2007            sts_paddr = _v2p_translate( vaddr , &flags );
2008
2009            // checking status address alignment
2010            if ( sts_paddr & 0x3F )
2011            {
2012                _printf("\n[GIET ERROR] in _sys_nic_alloc() : "
2013                        "status address of cluster[%d,%d] not aligned\n", cx, cy);
2014                return -1111;
2015            }
2016
2017            // initialize chbuf entry
2018            // The buffer descriptor has the following structure:
2019            // - the 26 LSB bits contain bits[6:31] of the buffer physical address
2020            // - the 26 following bits contain bits[6:31] of the physical address where the
2021            //   buffer status is located
2022            // - the 12 MSB bits contain the common address extension of the buffer and its
2023            //   status
2024            if ( is_rx )
2025                _nic_ker_rx_chbuf[nic_channel].buf_desc[index] =
2026                    (unsigned long long)
2027                    ((sts_paddr & 0xFFFFFFFFULL) >> 6) +
2028                    (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26);
2029            else
2030                _nic_ker_tx_chbuf[nic_channel].buf_desc[index] =
2031                    (unsigned long long)
2032                    ((sts_paddr & 0xFFFFFFC0ULL) >> 6) +
2033                    (((cont_paddr & 0xFFFFFFFFFC0ULL) >> 6) << 26);
2034
2035#if GIET_DEBUG_NIC
2036_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()\n"
2037        " - status vaddr = %x / paddr = %l\n"
2038        " Buffer descriptor = %l\n",
2039        thread, vaddr, sts_paddr,
2040        (unsigned long long)((sts_paddr & 0xFFFFFFFFULL) >> 6) + 
2041        (((cont_paddr & 0xFFFFFFFFFFFULL) >> 6) << 26) );
2042#endif
2043        }
2044    }
2045
2046    // complete kernel chbuf initialisation
2047    if ( is_rx )
2048    {
2049        _nic_ker_rx_chbuf[nic_channel].xmax = xmax;
2050        _nic_ker_rx_chbuf[nic_channel].ymax = ymax;
2051    }
2052    else
2053    {
2054        _nic_ker_tx_chbuf[nic_channel].xmax = xmax;
2055        _nic_ker_tx_chbuf[nic_channel].ymax = ymax;
2056    }
2057
2058    // compute the kernel chbuf descriptor physical address
2059    if ( is_rx ) vaddr = (unsigned int)( &_nic_ker_rx_chbuf[nic_channel] );
2060    else         vaddr = (unsigned int)( &_nic_ker_tx_chbuf[nic_channel] );
2061
2062    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
2063
2064#if GIET_DEBUG_NIC
2065_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
2066        "  vaddr = %x / paddr = %l\n",
2067        thread , vaddr , ker_chbuf_pbase );
2068#endif
2069
2070    // sync the kernel chbuf in L2 after write in L2
2071    _mmc_sync( ker_chbuf_pbase, sizeof( ker_chbuf_t ) );
2072
2073    ///////////////////////////////////////////////////////////////
2074    // Step 3: compute the NIC chbuf descriptor physical address //
2075    ///////////////////////////////////////////////////////////////
2076
2077    unsigned int offset;
2078    if ( is_rx ) offset = 0x4100;
2079    else         offset = 0x4110;
2080    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
2081                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
2082
2083#if GIET_DEBUG_NIC
2084_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
2085        thread , nic_chbuf_pbase );
2086#endif
2087
2088    ////////////////////////////////////////////////////////////////////////////////
2089    // Step 4: initialize CMA registers defining the source & destination chbufs //
2090    ////////////////////////////////////////////////////////////////////////////////
2091
2092    if ( is_rx )               // NIC to kernel
2093    {
2094        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
2095        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
2096        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
2097        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
2098        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
2099        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
2100    }
2101    else                      // kernel to NIC
2102    {
2103        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
2104        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
2105        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
2106        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
2107        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
2108        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
2109    }
2110
2111#if GIET_DEBUG_NIC
2112_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
2113        thread, _get_proctime() );
2114#endif
2115
2116    return GIET_SYSCALL_OK;
2117} // end _sys_nic_alloc()
2118
2119
2120//////////////////////////////////////////
2121int _sys_nic_release( unsigned int is_rx )     // NOTE: not a syscall
2122{
2123    unsigned int trdid = _get_thread_trdid();
2124
2125    unsigned int nic_channel;
2126    unsigned int cma_channel;
2127   
2128    // update the kernel tables
2129    if ( is_rx )
2130    {
2131        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2132        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
2133
2134        if ( (nic_channel >= NB_NIC_CHANNELS) )
2135        {
2136            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2137                    "NIC_RX channel already released for thread %x\n", trdid );
2138            return -1111;
2139        }
2140        if ( (cma_channel >= NB_CMA_CHANNELS) )
2141        {
2142            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2143                    "CMA_RX channel already released for thread %x\n", trdid );
2144            return -1111;
2145        }
2146
2147        // atomically decrement the NIC and CMA channel allocators
2148        _atomic_increment( &_nic_rx_channel_alloc[nic_channel] , -1 );
2149        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
2150   
2151        // stop the NIC and CMA peripherals channels if no more users
2152        if ( (_nic_rx_channel_alloc[nic_channel] == 0) &&
2153             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 1 );
2154
2155        // reset the calling thread context slots
2156        _set_context_slot( CTX_NIC_RX_ID , 0xFFFFFFFF );
2157        _set_context_slot( CTX_CMA_RX_ID , 0xFFFFFFFF );
2158    }         
2159    else
2160    {
2161        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2162        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
2163
2164        if ( (nic_channel >= NB_NIC_CHANNELS) )
2165        {
2166            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2167                    "NIC_TX channel already released for thread %x\n", trdid );
2168            return -1111;
2169        }
2170        if ( (cma_channel >= NB_CMA_CHANNELS) )
2171        {
2172            _printf("\n[GIET ERROR] in _sys_nic_release() : "
2173                    "CMA_TX channel already released for thread %x\n", trdid );
2174            return -1111;
2175        }
2176
2177        // atomically decrement the NIC and CMA channel allocators
2178        _atomic_increment( &_nic_tx_channel_alloc[nic_channel] , -1 );
2179        _atomic_increment( &_cma_channel_alloc[cma_channel] , -1 );
2180   
2181        // stop the NIC and CMA peripherals channels if no more users
2182        if ( (_nic_tx_channel_alloc[nic_channel] == 0) &&
2183             (_cma_channel_alloc[cma_channel] == 0) )  _sys_nic_stop( 0 );
2184
2185        // reset the calling thread context slots
2186        _set_context_slot( CTX_NIC_TX_ID , 0xFFFFFFFF );
2187        _set_context_slot( CTX_CMA_TX_ID , 0xFFFFFFFF );
2188    }
2189
2190    return GIET_SYSCALL_OK;
2191}  // end sys_nic_release()
2192
2193
2194////////////////////////////////////////
2195int _sys_nic_start( unsigned int is_rx )
2196{
2197    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2198
2199    unsigned int nic_channel;
2200    unsigned int cma_channel;
2201
2202    // get NIC channel index and CMA channel index from thread context
2203    if ( is_rx )
2204    {
2205        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2206        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
2207    }
2208    else
2209    {
2210        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2211        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
2212    }
2213
2214#if GIET_DEBUG_NIC
2215_printf("\n[GIET DEBUG NIC] Thread %x in _sys_nic_start() at cycle %d\n"
2216        "  get NIC channel = %d / CMA channel = %d\n",
2217        trdid, _get_proctime(), nic_channel, cma_channel );
2218#endif
2219
2220    // check NIC and CMA channels index
2221    if ( nic_channel >= NB_NIC_CHANNELS )
2222    {
2223        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
2224                "illegal NIC channel for thread %x\n", trdid );
2225        return -1111;
2226    }
2227    if ( cma_channel >= NB_CMA_CHANNELS )
2228    {
2229        _printf("\n[GIET_ERROR] in _sys_nic_start() : "
2230                "illegal CMA channel for thread %x\n", trdid );
2231        return -1111;
2232    }
2233
2234    // start CMA transfer
2235    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
2236    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
2237    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
2238
2239    // activates NIC channel
2240    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 );
2241
2242#if GIET_DEBUG_NIC
2243    _printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
2244            trdid , _get_proctime() );
2245#endif
2246
2247    return GIET_SYSCALL_OK;
2248}  // end _sys_nic_start()
2249
2250
2251//////////////////////////////////////
2252int _sys_nic_move( unsigned int is_rx,
2253                   void*        buffer )
2254{
2255    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2256
2257    unsigned int channel;
2258
2259#if GIET_DEBUG_NIC
2260_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
2261        trdid , _get_proctime() );
2262#endif
2263
2264    // get NIC channel index from thread context
2265    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
2266    else          channel = _get_context_slot( CTX_NIC_TX_ID );
2267
2268    // check NIC channel index
2269    if ( channel >= NB_NIC_CHANNELS )
2270    {
2271        _printf("\n[GIET_ERROR] in _sys_nic_move() : "
2272                "illegal NIC channel index for thread %x\n", trdid );
2273        return -1111;
2274    }
2275
2276    // get kernel chbuf virtual address
2277    ker_chbuf_t* ker_chbuf;
2278    if ( is_rx )  ker_chbuf = &_nic_ker_rx_chbuf[channel];
2279    else          ker_chbuf = &_nic_ker_tx_chbuf[channel];
2280
2281    // get xmax / ymax parameters
2282    unsigned int xmax = ker_chbuf->xmax;
2283    unsigned int ymax = ker_chbuf->ymax;
2284
2285    // get cluster coordinates for the processor running the calling thread
2286    unsigned int  procid = _get_procid();
2287    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
2288    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
2289   
2290    // check processor coordinates / (xmax,ymax)
2291    if ( cx >= xmax )
2292    {
2293        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
2294                " / xmax = %d\n", cx , xmax );
2295        return -1111;
2296    }
2297    if ( cy >= ymax )
2298    {
2299        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
2300                " / ymax = %d\n", cy , ymax );
2301        return -1111;
2302    }
2303   
2304    unsigned long long usr_buf_paddr;       // user buffer physical address
2305    unsigned long long ker_buf_paddr;       // kernel buffer physical address
2306    unsigned long long ker_sts_paddr;       // kernel buffer status physical address
2307    unsigned long long ker_buf_desc;        // kernel buffer descriptor
2308    unsigned int       ker_sts;             // kernel buffer status (full or empty)
2309    unsigned int       index;               // kernel buffer index in chbuf
2310    unsigned int       flags;               // for _v2P_translate
2311
2312    // Compute user buffer physical address and check access rights
2313    usr_buf_paddr = _v2p_translate( (unsigned int)buffer , &flags );
2314
2315    if ( (flags & PTE_U) == 0 )
2316    {
2317        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal user buffer address\n");
2318        return -1111;
2319    }
2320
2321#if GIET_DEBUG_NIC
2322_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
2323        thread, usr_buf_paddr );
2324#endif
2325
2326    // compute buffer index, buffer descriptor paddr and buffer status paddr
2327    index = (ymax * cx) + cy;
2328    ker_buf_desc = ker_chbuf->buf_desc[index];
2329    ker_sts_paddr = ((ker_buf_desc & 0xFFF0000000000000ULL) >> 20) +
2330                    ((ker_buf_desc & 0x3FFFFFFULL) << 6);
2331
2332#if GIET_DEBUG_NIC
2333_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_desc %d at cycle %d\n"
2334        "  kernel buffer descriptor = %l\n",
2335        thread, index, _get_proctime(), ker_buf_desc );
2336#endif
2337
2338    // poll local kernel container status until success
2339    while ( 1 )
2340    {
2341        // inval buffer descriptor in L2 before read in L2
2342        _mmc_inval( ker_sts_paddr, 4 );
2343        ker_sts = _physical_read( ker_sts_paddr );
2344
2345#if GIET_DEBUG_NIC
2346_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read ker_buf_sts %d at cycle %d\n"
2347        "  paddr = %l / kernel buffer status = %x\n",
2348        thread, index, _get_proctime(), ker_sts_paddr, ker_sts );
2349#endif
2350
2351        // test buffer status and break if found
2352        if ( ( is_rx != 0 ) && ( ker_sts == 0x1 ) ) break;
2353        if ( ( is_rx == 0 ) && ( ker_sts == 0 ) ) break;
2354    }
2355
2356    // compute kernel buffer physical address
2357    ker_buf_paddr = (ker_buf_desc & 0xFFFFFFFFFC000000ULL) >> 20;
2358   
2359    // move one container
2360    if ( is_rx )              // RX transfer
2361    {
2362        // inval kernel buffer in L2 before read in L2
2363        _mmc_inval( ker_buf_paddr, NIC_CONTAINER_SIZE );
2364
2365        // transfer data from kernel buffer to user buffer
2366        _physical_memcpy( usr_buf_paddr, 
2367                          ker_buf_paddr, 
2368                          NIC_CONTAINER_SIZE );
2369#if GIET_DEBUG_NIC
2370_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
2371        " to user buffer %l at cycle %d\n",
2372        thread , ker_buf_paddr , usr_buf_paddr , _get_proctime() );
2373#endif
2374
2375    }
2376    else                      // TX transfer
2377    {
2378        // transfer data from user buffer to kernel buffer
2379        _physical_memcpy( ker_buf_paddr, 
2380                          usr_buf_paddr, 
2381                          NIC_CONTAINER_SIZE );
2382
2383        // sync kernel buffer in L2 after write in L2
2384        _mmc_sync( ker_buf_paddr, NIC_CONTAINER_SIZE );
2385
2386#if GIET_DEBUG_NIC
2387_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
2388        "user buffer %l to kernel buffer %l at cycle %d\n",
2389        thread , usr_buf_paddr , ker_buf_paddr , _get_proctime() );
2390#endif
2391
2392    }
2393
2394    // update kernel chbuf status
2395    if ( is_rx ) _physical_write ( ker_sts_paddr, 0 );
2396    else         _physical_write ( ker_sts_paddr, 0x1 );
2397
2398    // sync kernel chbuf in L2 after write in L2
2399    _mmc_sync( ker_sts_paddr, 4 );
2400
2401#if GIET_DEBUG_NIC
2402_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
2403        thread , index , _get_proctime() );
2404#endif
2405
2406    return GIET_SYSCALL_OK;
2407} // end _sys_nic_move()
2408
2409
2410///////////////////////////////////////
2411int _sys_nic_stop( unsigned int is_rx )
2412{
2413    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2414
2415    unsigned int nic_channel;
2416    unsigned int cma_channel;
2417
2418    // get NIC channel index and CMA channel index
2419    if ( is_rx )
2420    {
2421        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2422        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
2423    }
2424    else
2425    {
2426        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2427        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
2428    }
2429
2430    // check NIC and CMA channels index
2431    if ( nic_channel >= NB_NIC_CHANNELS )
2432    {
2433        _printf("\n[GIET_ERROR] in _sys_nic_stop() : " 
2434                "illegal NIC channel for thread %x\n", trdid );
2435        return -1111;
2436    }
2437    if ( cma_channel >= NB_CMA_CHANNELS )
2438    {
2439        _printf("\n[GIET_ERROR] in _sys_nic_stop() : "
2440                "illegal CMA channel for thread %x\n", trdid );
2441        return -1111;
2442    }
2443
2444    // desactivates the CMA channel
2445    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
2446
2447    // wait until CMA channel IDLE
2448    unsigned int volatile status;
2449    do
2450    {
2451         status = _cma_get_register( cma_channel, CHBUF_STATUS );
2452    } while ( status ); 
2453
2454    // desactivates the NIC channel
2455    _nic_channel_stop( nic_channel, is_rx );
2456
2457    return GIET_SYSCALL_OK;
2458}  // end _sys_nic_stop()
2459
2460////////////////////////////////////////
2461int _sys_nic_clear( unsigned int is_rx )
2462{
2463    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2464
2465    unsigned int channel;
2466
2467    // get NIC channel
2468    if ( is_rx )  channel = _get_context_slot( CTX_NIC_RX_ID );
2469    else          channel = _get_context_slot( CTX_NIC_TX_ID );
2470
2471    if ( channel >= NB_NIC_CHANNELS )
2472    {
2473        _printf("\n[GIET_ERROR] in _sys_nic_clear() : "
2474                "illegal NIC channel for thread %x\n", trdid );
2475        return -1111;
2476    }
2477
2478    if ( is_rx )
2479    {
2480        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
2481        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
2482        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
2483        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
2484        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
2485        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
2486        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
2487        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
2488        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
2489    } 
2490    else
2491    {
2492        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
2493        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
2494        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
2495        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
2496        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
2497        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
2498        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
2499    }
2500    return GIET_SYSCALL_OK;
2501}  // en _sys_nic_clear()
2502
2503////////////////////////////////////////
2504int _sys_nic_stats( unsigned int is_rx )
2505{
2506    unsigned int trdid  = _get_context_slot( CTX_TRDID_ID );
2507
2508    unsigned int nic_channel;
2509
2510    // get NIC channel
2511    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
2512    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
2513
2514    if ( nic_channel >= NB_NIC_CHANNELS )
2515    {
2516        _printf("\n[GIET_ERROR] in _sys_nic_stats() : "
2517                "illegal NIC channel for thread %x\n", trdid );
2518        return -1111;
2519    }
2520
2521    if ( is_rx )
2522    {
2523        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
2524        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
2525        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
2526        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
2527        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
2528        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
2529        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
2530        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
2531
2532        _printf("\n### Network Controller RX Statistics ###\n"
2533                "- packets received : %d\n"
2534                "- too small        : %d\n"
2535                "- too big          : %d\n"
2536                "- fifo full        : %d\n" 
2537                "- crc fail         : %d\n" 
2538                "- dst mac fail     : %d\n" 
2539                "- channel full     : %d\n" 
2540                "- broadcast        : %d\n",
2541                received,
2542                too_small,
2543                too_big,
2544                fifo_full,
2545                crc_fail,
2546                dst_fail,
2547                ch_full,
2548                broadcast );
2549    } 
2550    else
2551    {
2552        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
2553        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
2554        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
2555        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
2556        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
2557        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
2558
2559        _printf("\n### Network Controller TX Statistics ###\n"
2560                "- packets received : %d\n"
2561                "- too small        : %d\n"
2562                "- too big          : %d\n"
2563                "- src mac fail     : %d\n" 
2564                "- bypass           : %d\n" 
2565                "- broadcast        : %d\n",
2566                received,
2567                too_big,
2568                too_small,
2569                src_fail,
2570                bypass,
2571                broadcast );
2572    }
2573    return GIET_SYSCALL_OK;
2574}  // end _sys_nic_stats()
2575
2576#endif
2577
2578/////////////////////////////////////////////////////////////////////////////////////////
2579//    FBF related syscall handlers
2580/////////////////////////////////////////////////////////////////////////////////////////
2581
2582/////////////////////////////////////////////
2583int _sys_fbf_sync_write( unsigned int offset,
2584                         void*        buffer,
2585                         unsigned int length )
2586{
2587    char* fbf_address = (char *)SEG_FBF_BASE + offset;
2588    memcpy( fbf_address, buffer, length);
2589
2590    return GIET_SYSCALL_OK;
2591}
2592
2593/////////////////////////////////////////////
2594int _sys_fbf_sync_read(  unsigned int offset,
2595                         void*        buffer,
2596                         unsigned int length )
2597{
2598    char* fbf_address = (char *)SEG_FBF_BASE + offset;
2599    memcpy( buffer, fbf_address, length);
2600
2601    return GIET_SYSCALL_OK;
2602}
2603
2604////////////////////////
2605int _sys_fbf_cma_alloc()
2606{
2607    unsigned int trdid = _get_thread_trdid();
2608
2609    if ( _get_context_slot( CTX_CMA_FB_ID ) < NB_CMA_CHANNELS )
2610    {
2611        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : "
2612                "CMA channel already allocated for thread %x\n", trdid );
2613        return GIET_SYSCALL_OK;
2614    }
2615
2616    // get a CMA channel
2617    unsigned int channel;
2618    for ( channel = 0 ; channel < NB_CMA_CHANNELS ; channel++ )
2619    {
2620        unsigned int*  palloc = &_cma_channel_alloc[channel];
2621        if ( _atomic_test_and_set( palloc , 1 ) == 0 ) break;
2622    }
2623    if ( channel >= NB_CMA_CHANNELS )
2624    {
2625        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : no CMA channel available\n");
2626        return -1111;
2627    }
2628    else
2629    {
2630        _set_context_slot( CTX_CMA_FB_ID, channel );
2631        return GIET_SYSCALL_OK;
2632    }
2633} // end sys_fbf_cma_alloc()
2634
2635//////////////////////////
2636int _sys_fbf_cma_release()  // Not a syscall
2637{
2638    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
2639    unsigned int trdid   = _get_thread_trdid();
2640
2641    if ( channel >= NB_CMA_CHANNELS )
2642    {
2643        _printf("\n[GIET_ERROR] in _sys_fbf_cma_release() : "
2644                "CMA_FB channel already releasedifor thread %x\n", trdid );
2645        return -1111;
2646    }
2647
2648    // stop CMA transfer
2649    _sys_fbf_cma_stop();
2650
2651    // reset CTX_CMA_FB_ID for thread
2652    _set_context_slot( CTX_CMA_FB_ID, 0xFFFFFFFF );
2653
2654    // release CMA channel
2655    _cma_channel_alloc[channel] = 0;
2656
2657    return GIET_SYSCALL_OK;
2658}
2659
2660///////////////////////////////////////////////////
2661int _sys_fbf_cma_init_buf( void*        buf0_vbase, 
2662                           void*        buf1_vbase, 
2663                           void*        sts0_vaddr,
2664                           void*        sts1_vaddr )
2665{
2666#if NB_CMA_CHANNELS > 0
2667
2668    unsigned int       vaddr;           // virtual address
2669    unsigned int       flags;           // for _v2p_translate()
2670    unsigned long long fbf_paddr;       // fbf physical address
2671    unsigned long long fbf_sts_paddr;   // fbf status physical address
2672    unsigned long long buf0_pbase;      // buffer 0 base physical address
2673    unsigned long long sts0_paddr;      // buffer 0 status physical address
2674    unsigned long long buf1_pbase;      // buffer 1 base physical address
2675    unsigned long long sts1_paddr;      // buffer 1 status physical address
2676
2677    // get channel index
2678    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
2679
2680    if ( channel >= NB_CMA_CHANNELS )
2681    {
2682        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n");
2683        return -1111;
2684    }
2685
2686#if GIET_DEBUG_FBF_CMA
2687_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_init_buf()\n"
2688        " - channel           = %d\n"
2689        " - buf0        vbase = %x\n"
2690        " - buf1        vbase = %x\n"
2691        " - sts0        vaddr = %x\n"
2692        " - sts1        vaddr = %x\n",
2693        channel,
2694        (unsigned int)buf0_vbase,
2695        (unsigned int)buf1_vbase,
2696        (unsigned int)sts0_vaddr,
2697        (unsigned int)sts1_vaddr );
2698#endif
2699
2700    // checking user buffers virtual addresses alignment
2701    if ( ((unsigned int)buf0_vbase & 0x3F) || 
2702         ((unsigned int)buf1_vbase & 0x3F) ) 
2703    {
2704        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n");
2705        return -1111;
2706    }
2707
2708    // checking user buffers status virtual addresses alignment
2709    if ( ((unsigned int)sts0_vaddr & 0x3F) ||
2710         ((unsigned int)sts1_vaddr & 0x3F) )
2711    {
2712        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n");
2713        return -1111;
2714    }
2715
2716    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
2717    vaddr = (unsigned int)SEG_FBF_BASE;
2718    fbf_paddr = _v2p_translate( vaddr , &flags );
2719    vaddr = (unsigned int)&_fbf_status[channel];
2720    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
2721
2722    _fbf_chbuf[channel].fbf_desc =
2723        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
2724        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
2725
2726    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
2727    vaddr = (unsigned int)buf0_vbase;
2728    buf0_pbase = _v2p_translate( vaddr , &flags );
2729    if ((flags & PTE_U) == 0) 
2730    {
2731        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n");
2732        return -1111;
2733    }
2734
2735    vaddr = (unsigned int)sts0_vaddr;
2736    sts0_paddr = _v2p_translate( vaddr , &flags );
2737    if ((flags & PTE_U) == 0) 
2738    {
2739        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n");
2740        return -1111;
2741    }
2742
2743    _fbf_chbuf[channel].buf0_desc = 
2744        (unsigned long long) ((sts0_paddr & 0xFFFFFFFFULL) >> 6) +
2745        (((buf0_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
2746
2747    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
2748    vaddr = (unsigned int)buf1_vbase;
2749    buf1_pbase = _v2p_translate( vaddr , &flags );
2750    if ((flags & PTE_U) == 0) 
2751    {
2752        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n");
2753        return -1111;
2754    }
2755
2756    vaddr = (unsigned int)sts1_vaddr;
2757    sts1_paddr = _v2p_translate( vaddr , &flags );
2758    if ((flags & PTE_U) == 0) 
2759    {
2760        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n");
2761        return -1111;
2762    }
2763
2764    _fbf_chbuf[channel].buf1_desc = 
2765        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
2766        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
2767
2768    // Compute and register physical adress of the fbf_chbuf descriptor
2769    vaddr = (unsigned int)&_fbf_chbuf[channel];
2770    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
2771 
2772#if GIET_DEBUG_FBF_CMA
2773_printf(" - fbf         pbase = %l\n"
2774        " - fbf status  paddr = %l\n"
2775        " - buf0        pbase = %l\n"
2776        " - buf0 status paddr = %l\n" 
2777        " - buf1        pbase = %l\n"
2778        " - buf0 status paddr = %l\n" 
2779        " - chbuf       pbase = %l\n",
2780        fbf_paddr,
2781        fbf_sts_paddr,
2782        buf0_pbase,
2783        sts0_paddr,
2784        buf1_pbase,
2785        sts1_paddr,
2786        _fbf_chbuf_paddr[channel] );
2787#endif
2788
2789    return GIET_SYSCALL_OK;
2790
2791#else
2792
2793    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
2794    return -1111;
2795
2796#endif 
2797} // end sys_fbf_cma_init_buf()
2798
2799////////////////////////////////////////////
2800int _sys_fbf_cma_start( unsigned int length ) 
2801{
2802#if NB_CMA_CHANNELS > 0
2803
2804    // get channel index
2805    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
2806
2807    if ( channel >= NB_CMA_CHANNELS )
2808    {
2809        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
2810        return -1111;
2811    }
2812
2813    // check buffers initialization
2814    if ( ( _fbf_chbuf[channel].buf0_desc == 0x0ULL ) &&
2815         ( _fbf_chbuf[channel].buf1_desc == 0x0ULL) &&
2816         ( _fbf_chbuf[channel].fbf_desc == 0x0ULL) )
2817    {
2818        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
2819                "Buffer initialization has not been done\n");
2820        return -1111;
2821    }
2822
2823    // initializes buffer length
2824    _fbf_chbuf[channel].length = length;
2825
2826    if ( USE_IOB )
2827    {
2828        // SYNC request for fbf_chbuf descriptor
2829        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
2830    }
2831
2832    // start CMA transfer
2833    unsigned long long paddr = _fbf_chbuf_paddr[channel];
2834    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
2835    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
2836    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
2837    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
2838
2839    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
2840    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
2841    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
2842    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
2843    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
2844    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
2845    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
2846    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
2847    _cma_set_register( channel, CHBUF_RUN      , 1 );
2848
2849    return GIET_SYSCALL_OK;
2850
2851#else
2852
2853    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
2854    return -1111;
2855
2856#endif
2857} // end _sys_fbf_cma_start()
2858
2859/////////////////////////////////////////////////////
2860int _sys_fbf_cma_display( unsigned int buffer_index )
2861{
2862#if NB_CMA_CHANNELS > 0
2863
2864    volatile unsigned int full = 1;
2865
2866    // get channel index
2867    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
2868
2869    if ( channel >= NB_CMA_CHANNELS )
2870    {
2871        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
2872                "CMA channel index too large\n");
2873        return -1111;
2874    }
2875
2876    // get fbf_chbuf descriptor pointer
2877    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
2878
2879#if GIET_DEBUG_FBF_CMA
2880_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
2881        " - cma channel      = %d\n"
2882        " - buffer index     = %d\n"
2883        " - buf0_desc value  = %l\n"
2884        " - buf1_desc value  = %l\n"
2885        " - fbf_desc  value  = %l\n",
2886        channel , buffer_index,
2887        _fbf_chbuf[channel].buf0_desc,
2888        _fbf_chbuf[channel].buf1_desc,
2889        _fbf_chbuf[channel].fbf_desc );
2890#endif
2891
2892    unsigned long long buf_sts_paddr;
2893    unsigned long long buf_paddr;
2894    unsigned long long fbf_sts_paddr;
2895
2896    if ( buffer_index == 0 )    // user buffer 0
2897    {
2898        buf_sts_paddr =
2899            ((pdesc->buf0_desc & 0xFFF0000000000000ULL) >> 20) + // compute address extension
2900            ((pdesc->buf0_desc & 0x3FFFFFFULL) << 6);            // compute 32 LSB of the address
2901
2902        buf_paddr =
2903            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
2904    }
2905    else                        // user buffer 1
2906    {
2907        buf_sts_paddr =
2908            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
2909            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
2910
2911        buf_paddr =
2912            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
2913    }
2914
2915    fbf_sts_paddr =
2916        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
2917        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
2918
2919#if GIET_DEBUG_FBF_CMA
2920_printf(" - fbf status paddr = %l\n"
2921        " - buf        pbase = %l\n"
2922        " - buf status paddr = %l\n",
2923        fbf_sts_paddr,
2924        buf_paddr,
2925        buf_sts_paddr );
2926#endif
2927       
2928    // waiting user buffer released by the CMA component)
2929    while ( full )
2930    { 
2931        // INVAL L2 cache copy of user buffer status     
2932        // because it has been modified in RAM by the CMA component
2933        _mmc_inval( buf_sts_paddr , 4 );       
2934
2935        full = _physical_read( buf_sts_paddr );
2936    }
2937
2938    // SYNC request for the user buffer, because
2939    // it will be read from XRAM by the CMA component
2940    _mmc_sync( buf_paddr , pdesc->length );
2941
2942    // set user buffer status
2943    _physical_write( buf_sts_paddr, 0x1 );
2944
2945    // reset fbf buffer status
2946    _physical_write( fbf_sts_paddr, 0x0 );
2947   
2948    // SYNC request, because these buffer descriptors
2949    // will be read from XRAM by the CMA component
2950    _mmc_sync( buf_sts_paddr, 4 );
2951    _mmc_sync( fbf_sts_paddr, 4 );
2952
2953    return GIET_SYSCALL_OK;
2954
2955#else
2956
2957    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
2958    return -1111;
2959
2960#endif
2961} // end _sys_fbf_cma_display()
2962
2963///////////////////////
2964int _sys_fbf_cma_stop()
2965{
2966#if NB_CMA_CHANNELS > 0
2967
2968    // get channel index
2969    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
2970
2971    if ( channel >= NB_CMA_CHANNELS )
2972    {
2973        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
2974        return -1111;
2975    }
2976
2977    // Desactivate CMA channel
2978    _cma_set_register( channel, CHBUF_RUN, 0 );
2979
2980    return GIET_SYSCALL_OK;
2981
2982#else
2983
2984    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
2985    return -1111;
2986
2987#endif
2988} // end _sys_fbf_cma_stop()
2989
2990
2991//////////////////////////////////////////////////////////////////////////////
2992//           Miscelaneous syscall handlers
2993//////////////////////////////////////////////////////////////////////////////
2994
2995///////////////
2996int _sys_ukn() 
2997{
2998    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
2999    return GIET_SYSCALL_UNDEFINED_SYSTEM_CALL;
3000}
3001
3002////////////////////////////////////
3003int _sys_proc_xyp( unsigned int* x,
3004                   unsigned int* y,
3005                   unsigned int* p )
3006{
3007    unsigned int gpid = _get_procid();  // global processor index from CPO register
3008
3009    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
3010    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
3011    *p = gpid & ((1<<P_WIDTH)-1);
3012
3013    return GIET_SYSCALL_OK;
3014}
3015
3016////////////////////////////////////////////
3017int _sys_procs_number( unsigned int* x_size,
3018                       unsigned int* y_size,
3019                       unsigned int* nprocs )
3020{
3021    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
3022    mapping_cluster_t * cluster = _get_cluster_base(header);
3023
3024    unsigned int x;
3025    unsigned int y;
3026    unsigned int okmin = 1;
3027    unsigned int okmax = 1;
3028
3029    // compute max values
3030    unsigned int xmax  = header->x_size;
3031    unsigned int ymax  = header->y_size;
3032    unsigned int procs = cluster[0].procs;
3033
3034    // check the (ymax-1) lower rows
3035    for ( y = 0 ; y < ymax-1 ; y++ )
3036    {
3037        for ( x = 0 ; x < xmax ; x++ )
3038        {
3039            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
3040        }
3041    }
3042
3043    // check the upper row
3044    for ( x = 0 ; x < xmax ; x++ )
3045    {
3046        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
3047    }
3048
3049    // return values
3050    if ( okmin && okmax )
3051    {
3052        *x_size = xmax;
3053        *y_size = ymax;
3054        *nprocs = procs;
3055    }
3056    else if ( okmin )
3057    {
3058        *x_size = xmax;
3059        *y_size = ymax-1;
3060        *nprocs = procs;
3061    }
3062    else
3063    {
3064        *x_size = 0;
3065        *y_size = 0;
3066        *nprocs = 0;
3067    }
3068    return GIET_SYSCALL_OK;
3069}
3070
3071///////////////////////////////////////////////////////
3072int _sys_vseg_get_vbase( char*             vspace_name, 
3073                         char*             vseg_name, 
3074                         unsigned int*     vbase ) 
3075{
3076    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
3077    mapping_vspace_t * vspace = _get_vspace_base(header);
3078    mapping_vseg_t * vseg     = _get_vseg_base(header);
3079
3080    unsigned int vspace_id;
3081    unsigned int vseg_id;
3082
3083    // scan vspaces
3084    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
3085    {
3086        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
3087        {
3088            // scan vsegs
3089            for (vseg_id = vspace[vspace_id].vseg_offset; 
3090                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
3091                 vseg_id++) 
3092            {
3093                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
3094                {
3095                    *vbase = vseg[vseg_id].vbase;
3096                    return GIET_SYSCALL_OK;
3097                }
3098            } 
3099        }
3100    } 
3101    return GIET_SYSCALL_VSEG_NOT_FOUND;
3102}
3103
3104/////////////////////////////////////////////////////////
3105int _sys_vseg_get_length( char*         vspace_name, 
3106                          char*         vseg_name,
3107                          unsigned int* length ) 
3108{
3109    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
3110    mapping_vspace_t * vspace = _get_vspace_base(header);
3111    mapping_vseg_t * vseg     = _get_vseg_base(header);
3112
3113    unsigned int vspace_id;
3114    unsigned int vseg_id;
3115
3116    // scan vspaces
3117    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
3118    {
3119        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
3120        {
3121            // scan vsegs
3122            for (vseg_id = vspace[vspace_id].vseg_offset; 
3123                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
3124                 vseg_id++) 
3125            {
3126                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
3127                {
3128                    *length = vseg[vseg_id].length;
3129                    return GIET_SYSCALL_OK;
3130                }
3131            } 
3132        }
3133    } 
3134    return GIET_SYSCALL_VSEG_NOT_FOUND;
3135}
3136
3137////////////////////////////////////////
3138int _sys_xy_from_ptr( void*         ptr,
3139                      unsigned int* x,
3140                      unsigned int* y )
3141{
3142    unsigned int flags;
3143    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
3144   
3145    *x = (paddr>>36) & 0xF;
3146    *y = (paddr>>32) & 0xF;
3147
3148    return GIET_SYSCALL_OK;
3149}
3150
3151/////////////////////////////////////////
3152int _sys_heap_info( unsigned int* vaddr, 
3153                    unsigned int* length,
3154                    unsigned int  x,
3155                    unsigned int  y ) 
3156{
3157    // checking parameters
3158    if ( (x >= X_SIZE) || (y >= Y_SIZE) ) 
3159    {
3160        *vaddr  = 0;
3161        *length = 0;
3162        _printf("\n[GIET ERROR] in _sys_heap_info() : "
3163                "illegal (%d,%d) coordinates\n", x , y );
3164        return GIET_SYSCALL_ILLEGAL_CLUSTER_COORDINATES;
3165    }
3166
3167    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
3168    mapping_thread_t * thread  = _get_thread_base(header);
3169    mapping_vseg_t *   vseg    = _get_vseg_base(header);
3170    mapping_vspace_t * vspace  = _get_vspace_base(header);
3171
3172    unsigned int thread_id;
3173    unsigned int vspace_id;
3174    unsigned int vseg_id = 0xFFFFFFFF;
3175
3176    // get calling thread vspace index
3177    vspace_id = _get_context_slot(CTX_VSID_ID);
3178
3179    // scan all threads in vspace to find one in clyster[x,y]
3180    unsigned int min = vspace[vspace_id].thread_offset ;
3181    unsigned int max = min + vspace[vspace_id].threads ;
3182    for ( thread_id = min ; thread_id < max ; thread_id++ )
3183    {
3184        if ( thread[thread_id].clusterid == (x * Y_SIZE + y) )
3185        {
3186            vseg_id = thread[thread_id].heap_vseg_id;
3187            break;
3188        }
3189    }
3190
3191    // analysing the vseg_id
3192    if ( vseg_id != 0xFFFFFFFF ) 
3193    {
3194        *vaddr  = vseg[vseg_id].vbase;
3195        *length = vseg[vseg_id].length;
3196    }
3197    else 
3198    {
3199        *vaddr  = 0;
3200        *length = 0;
3201        _printf("error in _sys_heap_info() : no heap in cluster (%d,%d)\n", x , y );
3202    }
3203    return GIET_SYSCALL_OK;
3204}  // end _sys_heap_info()
3205
3206
3207// Local Variables:
3208// tab-width: 4
3209// c-basic-offset: 4
3210// c-file-offsets:((innamespace . 0)(inline-open . 0))
3211// indent-tabs-mode: nil
3212// End:
3213// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
3214
Note: See TracBrowser for help on using the repository browser.