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

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

kernel: defer task kill to _ctx_switch()

Introduce SIG slot in task context.
Add release functions for tty, tim and nic in sys_handler.
Process signals in _ctx_switch().

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