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

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

fat32: implement _fat_opendir, _fat_closedir, _fat_readdir

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