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

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

kernel: add fbf_cma release, call it on task kill

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