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

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

kernel: add fbf_cma release, call it on task kill

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