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

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

kernel: release WTI mailbox associated with TTY

We don't block on giet_tty_alloc() anymore when launching the same app
again and again.

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