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

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

kernel: use non-trivial CMA allocator

  • Property svn:executable set to *
File size: 77.3 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
[614]1688
[648]1689///////////////////////////////////////////////////
1690int _sys_fbf_cma_init_buf( void*        buf0_vbase, 
1691                           void*        buf1_vbase, 
1692                           void*        sts0_vaddr,
1693                           void*        sts1_vaddr )
[440]1694{
1695#if NB_CMA_CHANNELS > 0
1696
1697    unsigned int       vaddr;           // virtual address
[528]1698    unsigned int       flags;           // for _v2p_translate()
[614]1699    unsigned long long fbf_paddr;       // fbf physical address
1700    unsigned long long fbf_sts_paddr;   // fbf status physical address
1701    unsigned long long buf0_pbase;      // buffer 0 base physical address
1702    unsigned long long sts0_paddr;      // buffer 0 status physical address
1703    unsigned long long buf1_pbase;      // buffer 1 base physical address
1704    unsigned long long sts1_paddr;      // buffer 1 status physical address
[440]1705
1706    // get channel index
[449]1707    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]1708
1709    if ( channel >= NB_CMA_CHANNELS )
1710    {
[648]1711        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : CMA channel index too large\n");
[440]1712        return -1;
1713    }
1714
1715#if GIET_DEBUG_FBF_CMA
[614]1716_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_init_buf()\n"
1717        " - channel           = %d\n"
1718        " - buf0        vbase = %x\n"
1719        " - buf1        vbase = %x\n"
1720        " - sts0        vaddr = %x\n"
1721        " - sts1        vaddr = %x\n",
[440]1722        channel,
[614]1723        (unsigned int)buf0_vbase,
1724        (unsigned int)buf1_vbase,
1725        (unsigned int)sts0_vaddr,
1726        (unsigned int)sts1_vaddr );
[440]1727#endif
1728
[614]1729    // checking user buffers virtual addresses alignment
1730    if ( ((unsigned int)buf0_vbase & 0x3F) || 
1731         ((unsigned int)buf1_vbase & 0x3F) ) 
[440]1732    {
[648]1733        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user buffer not aligned\n");
[440]1734        return -1;
1735    }
1736
[614]1737    // checking user buffers status virtual addresses alignment
1738    if ( ((unsigned int)sts0_vaddr & 0x3F) ||
1739         ((unsigned int)sts1_vaddr & 0x3F) )
1740    {
[648]1741        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : user status not aligned\n");
[614]1742        return -1;
1743    }
1744
[440]1745    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
[528]1746    vaddr = (unsigned int)SEG_FBF_BASE;
[614]1747    fbf_paddr = _v2p_translate( vaddr , &flags );
1748    vaddr = (unsigned int)&_fbf_status[channel];
1749    fbf_sts_paddr = _v2p_translate( vaddr , &flags );
[440]1750
[614]1751    _fbf_chbuf[channel].fbf_desc =
1752        (unsigned long long) ((fbf_sts_paddr & 0xFFFFFFFFULL) >> 6) +
1753        (((fbf_paddr & 0xFFFFFFFFULL) >> 6 ) << 26);
1754
[528]1755    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
[614]1756    vaddr = (unsigned int)buf0_vbase;
1757    buf0_pbase = _v2p_translate( vaddr , &flags );
[440]1758    if ((flags & PTE_U) == 0) 
1759    {
[648]1760        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf0 not in user space\n");
[440]1761        return -1;
1762    }
1763
[614]1764    vaddr = (unsigned int)sts0_vaddr;
1765    sts0_paddr = _v2p_translate( vaddr , &flags );
1766    if ((flags & PTE_U) == 0) 
1767    {
[648]1768        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts0 not in user space\n");
[614]1769        return -1;
1770    }
1771
1772    _fbf_chbuf[channel].buf0_desc = 
1773        (unsigned long long) ((sts0_paddr & 0xFFFFFFFFULL) >> 6) +
1774        (((buf0_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1775
[528]1776    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
[614]1777    vaddr = (unsigned int)buf1_vbase;
1778    buf1_pbase = _v2p_translate( vaddr , &flags );
[440]1779    if ((flags & PTE_U) == 0) 
1780    {
[648]1781        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : buf1 not in user space\n");
[440]1782        return -1;
1783    }
1784
[614]1785    vaddr = (unsigned int)sts1_vaddr;
1786    sts1_paddr = _v2p_translate( vaddr , &flags );
1787    if ((flags & PTE_U) == 0) 
1788    {
[648]1789        _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : sts1 not in user space\n");
[614]1790        return -1;
1791    }
[440]1792
[614]1793    _fbf_chbuf[channel].buf1_desc = 
1794        (unsigned long long) ((sts1_paddr & 0xFFFFFFFFULL) >> 6) +
1795        (((buf1_pbase & 0xFFFFFFFFULL) >> 6 ) << 26);
1796
[505]1797    // Compute and register physical adress of the fbf_chbuf descriptor
[528]1798    vaddr = (unsigned int)&_fbf_chbuf[channel];
1799    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
[440]1800 
[614]1801#if GIET_DEBUG_FBF_CMA
1802_printf(" - fbf         pbase = %l\n"
1803        " - fbf status  paddr = %l\n"
1804        " - buf0        pbase = %l\n"
1805        " - buf0 status paddr = %l\n" 
1806        " - buf1        pbase = %l\n"
1807        " - buf0 status paddr = %l\n" 
1808        " - chbuf       pbase = %l\n",
1809        fbf_paddr,
1810        fbf_sts_paddr,
1811        buf0_pbase,
1812        sts0_paddr,
1813        buf1_pbase,
1814        sts1_paddr,
1815        _fbf_chbuf_paddr[channel] );
1816#endif
1817
1818    return 0;
1819
1820#else
1821
1822    _printf("\n[GIET ERROR] in _sys_fbf_cma_init_buf() : NB_CMA_CHANNELS = 0\n");
1823    return -1;
1824
1825#endif 
1826} // end sys_fbf_cma_init_buf()
1827
1828////////////////////////////////////////////
1829int _sys_fbf_cma_start( unsigned int length ) 
1830{
1831#if NB_CMA_CHANNELS > 0
1832
1833    // get channel index
1834    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1835
1836    if ( channel >= NB_CMA_CHANNELS )
1837    {
1838        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
1839        return -1;
1840    }
1841
1842    // check buffers initialization
1843    if ( ( _fbf_chbuf[channel].buf0_desc == 0x0ULL ) &&
1844         ( _fbf_chbuf[channel].buf1_desc == 0x0ULL) &&
1845         ( _fbf_chbuf[channel].fbf_desc == 0x0ULL) )
1846    {
1847        _printf("\n[GIET ERROR] in _sys_fbf_cma_start() :\n"
1848                "Buffer initialization has not been done\n");
1849        return -1;
1850    }
1851
1852    // initializes buffer length
1853    _fbf_chbuf[channel].length = length;
1854
[440]1855    if ( USE_IOB )
1856    {
[505]1857        // SYNC request for fbf_chbuf descriptor
1858        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
[440]1859    }
1860
[505]1861    // start CMA transfer
1862    unsigned long long paddr = _fbf_chbuf_paddr[channel];
1863    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
1864    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
[614]1865    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 16;
[505]1866    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
1867
1868    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
1869    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
1870    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
1871    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
1872    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
1873    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
1874    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
1875    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
1876    _cma_set_register( channel, CHBUF_RUN      , 1 );
1877
[440]1878    return 0;
1879
1880#else
1881
1882    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1883    return -1;
1884
1885#endif
1886} // end _sys_fbf_cma_start()
1887
1888/////////////////////////////////////////////////////
1889int _sys_fbf_cma_display( unsigned int buffer_index )
1890{
1891#if NB_CMA_CHANNELS > 0
1892
[505]1893    volatile unsigned int full = 1;
[440]1894
1895    // get channel index
[449]1896    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]1897
1898    if ( channel >= NB_CMA_CHANNELS )
1899    {
[505]1900        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1901                "CMA channel index too large\n");
[440]1902        return -1;
1903    }
1904
[505]1905    // get fbf_chbuf descriptor pointer
1906    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1907
[440]1908#if GIET_DEBUG_FBF_CMA
1909_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
[614]1910        " - cma channel      = %d\n"
1911        " - buffer index     = %d\n"
1912        " - buf0_desc value  = %l\n"
1913        " - buf1_desc value  = %l\n"
1914        " - fbf_desc  value  = %l\n",
[505]1915        channel , buffer_index,
[614]1916        _fbf_chbuf[channel].buf0_desc,
1917        _fbf_chbuf[channel].buf1_desc,
1918        _fbf_chbuf[channel].fbf_desc );
[440]1919#endif
1920
[614]1921    unsigned long long buf_sts_paddr;
1922    unsigned long long buf_paddr;
1923    unsigned long long fbf_sts_paddr;
1924
[478]1925    if ( buffer_index == 0 )    // user buffer 0
1926    {
[614]1927        buf_sts_paddr =
1928            ((pdesc->buf0_desc & 0xFFF0000000000000ULL) >> 20) + // compute address extension
1929            ((pdesc->buf0_desc & 0x3FFFFFFULL) << 6);            // compute 32 LSB of the address
[505]1930
[614]1931        buf_paddr =
1932            (pdesc->buf0_desc & 0xFFFFFFFFFC000000ULL) >> 20;  // compute the entire address
[440]1933    }
[478]1934    else                        // user buffer 1
1935    {
[614]1936        buf_sts_paddr =
1937            ((pdesc->buf1_desc & 0xFFF0000000000000ULL) >> 20) +
1938            ((pdesc->buf1_desc & 0x3FFFFFFULL) << 6);
[505]1939
[614]1940        buf_paddr =
1941            (pdesc->buf1_desc & 0xFFFFFFFFFC000000ULL) >> 20;
1942    }
[478]1943
[614]1944    fbf_sts_paddr =
1945        ((pdesc->fbf_desc & 0xFFF0000000000000ULL) >> 20) +
1946        ((pdesc->fbf_desc & 0x3FFFFFFULL) << 6);
[440]1947
[614]1948#if GIET_DEBUG_FBF_CMA
1949_printf(" - fbf status paddr = %l\n"
1950        " - buf        pbase = %l\n"
1951        " - buf status paddr = %l\n",
1952        fbf_sts_paddr,
1953        buf_paddr,
1954        buf_sts_paddr );
1955#endif
1956       
1957    // waiting user buffer released by the CMA component)
1958    while ( full )
1959    { 
[648]1960        // INVAL L2 cache copy of user buffer status     
[614]1961        // because it has been modified in RAM by the CMA component
1962        _mmc_inval( buf_sts_paddr , 4 );       
[440]1963
[614]1964        full = _physical_read( buf_sts_paddr );
[440]1965    }
1966
[614]1967    // SYNC request for the user buffer, because
1968    // it will be read from XRAM by the CMA component
1969    _mmc_sync( buf_paddr , pdesc->length );
[440]1970
[614]1971    // set user buffer status
1972    _physical_write( buf_sts_paddr, 0x1 );
1973
1974    // reset fbf buffer status
1975    _physical_write( fbf_sts_paddr, 0x0 );
1976   
1977    // SYNC request, because these buffer descriptors
1978    // will be read from XRAM by the CMA component
1979    _mmc_sync( buf_sts_paddr, 4 );
1980    _mmc_sync( fbf_sts_paddr, 4 );
1981
[440]1982    return 0;
1983
1984#else
1985
1986    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1987    return -1;
1988
1989#endif
1990} // end _sys_fbf_cma_display()
1991
1992///////////////////////
1993int _sys_fbf_cma_stop()
1994{
1995#if NB_CMA_CHANNELS > 0
1996
1997    // get channel index
[449]1998    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
[440]1999
2000    if ( channel >= NB_CMA_CHANNELS )
2001    {
2002        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
2003        return -1;
2004    }
2005
2006    // Desactivate CMA channel
[505]2007    _cma_set_register( channel, CHBUF_RUN, 0 );
[440]2008
2009    return 0;
2010
2011#else
2012
2013    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
2014    return -1;
2015
2016#endif
2017} // end _sys_fbf_cma_stop()
2018
2019
2020//////////////////////////////////////////////////////////////////////////////
2021//           Miscelaneous syscall handlers
2022//////////////////////////////////////////////////////////////////////////////
2023
2024///////////////
2025int _sys_ukn() 
2026{
2027    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
2028    return -1;
2029}
2030
2031////////////////////////////////////
2032int _sys_proc_xyp( unsigned int* x,
2033                   unsigned int* y,
2034                   unsigned int* p )
2035{
[428]2036    unsigned int gpid = _get_procid();  // global processor index from CPO register
2037
2038    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
2039    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
2040    *p = gpid & ((1<<P_WIDTH)-1);
[440]2041
2042    return 0;
[428]2043}
[440]2044
2045//////////////////////////////////
2046int _sys_task_exit( char* string ) 
[258]2047{
[294]2048    unsigned int date       = _get_proctime();
[428]2049
2050    unsigned int gpid       = _get_procid();
2051    unsigned int cluster_xy = gpid >> P_WIDTH;
[294]2052    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
2053    unsigned int x          = cluster_xy >> Y_WIDTH;
[629]2054    unsigned int p          = gpid & ((1<<P_WIDTH)-1);
[428]2055
[629]2056    unsigned int ltid       = _get_context_slot(CTX_LTID_ID);
[258]2057
[440]2058    // print exit message
[294]2059    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
2060            "\n       Cause : %s\n\n",
[629]2061            ltid, x, y, p, date, string );
[258]2062
[629]2063    // set NORUN_MASK_TASK bit (non runnable state)
2064    static_scheduler_t*  psched  = (static_scheduler_t*)_schedulers[x][y][p];
2065    unsigned int*        ptr     = &psched->context[ltid][CTX_NORUN_ID];
2066    _atomic_or( ptr , NORUN_MASK_TASK );
[258]2067
2068    // deschedule
[528]2069    _sys_context_switch();
[440]2070
2071    return 0;
[258]2072} 
2073
[528]2074/////////////////////////
2075int _sys_context_switch() 
[258]2076{
[440]2077    unsigned int save_sr;
[258]2078
[440]2079    _it_disable( &save_sr );
2080    _ctx_switch();
2081    _it_restore( &save_sr );
2082
2083    return 0;
[258]2084}
2085
[440]2086////////////////////////
2087int _sys_local_task_id()
[258]2088{
2089    return _get_context_slot(CTX_LTID_ID);
2090}
2091
[440]2092/////////////////////////
2093int _sys_global_task_id()
[258]2094{
2095    return _get_context_slot(CTX_GTID_ID);
2096}
2097
[440]2098////////////////////
2099int _sys_thread_id()
[267]2100{
2101    return _get_context_slot(CTX_TRDID_ID);
2102}
2103
[494]2104////////////////////////////////////////////
2105int _sys_procs_number( unsigned int* x_size,
2106                       unsigned int* y_size,
2107                       unsigned int* nprocs )
[258]2108{
[494]2109    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[440]2110    mapping_cluster_t * cluster = _get_cluster_base(header);
2111
[494]2112    unsigned int x;
2113    unsigned int y;
2114    unsigned int okmin = 1;
2115    unsigned int okmax = 1;
2116
2117    // compute max values
2118    unsigned int xmax  = header->x_size;
2119    unsigned int ymax  = header->y_size;
2120    unsigned int procs = cluster[0].procs;
2121
2122    // check the (ymax-1) lower rows
2123    for ( y = 0 ; y < ymax-1 ; y++ )
[440]2124    {
[494]2125        for ( x = 0 ; x < xmax ; x++ )
2126        {
2127            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
2128        }
[440]2129    }
[494]2130
2131    // check the upper row
2132    for ( x = 0 ; x < xmax ; x++ )
[440]2133    {
[494]2134        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
[440]2135    }
[494]2136
2137    // return values
2138    if ( okmin && okmax )
2139    {
2140        *x_size = xmax;
2141        *y_size = ymax;
2142        *nprocs = procs;
2143    }
2144    else if ( okmin )
2145    {
2146        *x_size = xmax;
2147        *y_size = ymax-1;
2148        *nprocs = procs;
2149    }
2150    else
2151    {
2152        *x_size = 0;
2153        *y_size = 0;
2154        *nprocs = 0;
2155    }
2156    return 0;
[440]2157}
2158
2159///////////////////////////////////////////////////////
[516]2160int _sys_vseg_get_vbase( char*             vspace_name, 
2161                         char*             vseg_name, 
[440]2162                         unsigned int*     vbase ) 
2163{
[322]2164    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[258]2165    mapping_vspace_t * vspace = _get_vspace_base(header);
[516]2166    mapping_vseg_t * vseg     = _get_vseg_base(header);
[258]2167
2168    unsigned int vspace_id;
[516]2169    unsigned int vseg_id;
[258]2170
2171    // scan vspaces
2172    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
2173    {
2174        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2175        {
[516]2176            // scan vsegs
2177            for (vseg_id = vspace[vspace_id].vseg_offset; 
2178                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
2179                 vseg_id++) 
[258]2180            {
[516]2181                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
[258]2182                {
[516]2183                    *vbase = vseg[vseg_id].vbase;
[258]2184                    return 0;
2185                }
2186            } 
2187        }
2188    } 
[440]2189    return -1;    // not found
[258]2190}
2191
[440]2192/////////////////////////////////////////////////////////
[516]2193int _sys_vseg_get_length( char*         vspace_name, 
2194                          char*         vseg_name,
[440]2195                          unsigned int* length ) 
[258]2196{
[440]2197    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2198    mapping_vspace_t * vspace = _get_vspace_base(header);
[516]2199    mapping_vseg_t * vseg     = _get_vseg_base(header);
[258]2200
[440]2201    unsigned int vspace_id;
[516]2202    unsigned int vseg_id;
[440]2203
2204    // scan vspaces
2205    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
[258]2206    {
[440]2207        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
2208        {
[516]2209            // scan vsegs
2210            for (vseg_id = vspace[vspace_id].vseg_offset; 
2211                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
2212                 vseg_id++) 
[440]2213            {
[516]2214                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
[440]2215                {
[516]2216                    *length = vseg[vseg_id].length;
[440]2217                    return 0;
2218                }
2219            } 
2220        }
2221    } 
2222    return -1;    // not found
[258]2223}
2224
[440]2225////////////////////////////////////////
2226int _sys_xy_from_ptr( void*         ptr,
2227                      unsigned int* x,
2228                      unsigned int* y )
[396]2229{
2230    unsigned int flags;
[528]2231    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
[396]2232   
[528]2233    *x = (paddr>>36) & 0xF;
2234    *y = (paddr>>32) & 0xF;
[396]2235
2236    return 0;
2237}
2238
[440]2239/////////////////////////////////////////
2240int _sys_heap_info( unsigned int* vaddr, 
2241                    unsigned int* length,
2242                    unsigned int  x,
2243                    unsigned int  y ) 
[258]2244{
[440]2245    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
[516]2246    mapping_task_t *   task    = _get_task_base(header);
2247    mapping_vseg_t *   vseg    = _get_vseg_base(header);
2248    mapping_vspace_t * vspace  = _get_vspace_base(header);
[294]2249
[440]2250    unsigned int task_id;
2251    unsigned int vspace_id;
[516]2252    unsigned int vseg_id = 0xFFFFFFFF;
[258]2253
[516]2254    // searching the heap vseg
[440]2255    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
2256    {
2257        // get vspace global index
2258        vspace_id = _get_context_slot(CTX_VSID_ID);
2259
2260        // scan all tasks in vspace
[516]2261        unsigned int min = vspace[vspace_id].task_offset ;
2262        unsigned int max = min + vspace[vspace_id].tasks ;
[440]2263        for ( task_id = min ; task_id < max ; task_id++ )
2264        {
[516]2265            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
[440]2266            {
[516]2267                vseg_id = task[task_id].heap_vseg_id;
2268                if ( vseg_id != 0xFFFFFFFF ) break;
[440]2269            }
2270        }
2271    }
2272    else                                // searching in the calling task
2273    {
2274        task_id = _get_context_slot(CTX_GTID_ID);
[516]2275        vseg_id = task[task_id].heap_vseg_id;
[440]2276    }
2277
[516]2278    // analysing the vseg_id
2279    if ( vseg_id != 0xFFFFFFFF ) 
[440]2280    {
[516]2281        *vaddr  = vseg[vseg_id].vbase;
2282        *length = vseg[vseg_id].length;
[440]2283        return 0;
2284    }
2285    else 
2286    {
2287        *vaddr  = 0;
2288        *length = 0;
2289        return -1;
2290    }
2291}  // end _sys_heap_info()
2292
2293
[688]2294///////////////////////
2295int _sys_tasks_status()
2296{
2297    mapping_header_t *  header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
2298    mapping_task_t *    task    = _get_task_base(header);
2299    mapping_vspace_t *  vspace  = _get_vspace_base(header);
2300    mapping_cluster_t * cluster = _get_cluster_base(header);
2301
2302    unsigned int task_id;
2303    unsigned int vspace_id;
2304
2305    // scan all vspaces
2306    for( vspace_id = 0 ; vspace_id < header->vspaces ; vspace_id++ )
2307    {
2308        _printf("\n*** vspace %s\n", vspace[vspace_id].name );
2309
2310        // scan all tasks in vspace
2311        unsigned int min = vspace[vspace_id].task_offset ;
2312        unsigned int max = min + vspace[vspace_id].tasks ;
2313        for ( task_id = min ; task_id < max ; task_id++ )
2314        {
2315            unsigned int         clusterid = task[task_id].clusterid;
2316            unsigned int         p         = task[task_id].proclocid;
2317            unsigned int         x         = cluster[clusterid].x;
2318            unsigned int         y         = cluster[clusterid].y;
2319            unsigned int         ltid      = task[task_id].ltid;
2320            static_scheduler_t*  psched    = (static_scheduler_t*)_schedulers[x][y][p];
2321            unsigned int         norun     = psched->context[ltid][CTX_NORUN_ID];
2322            unsigned int         current   = psched->current;
2323
2324            if ( current == ltid )
2325            _printf(" - task %s on P[%d,%d,%d] : running\n", task[task_id].name, x, y, p );
2326            else if ( norun == 0 )
[690]2327            _printf(" - task %s on P[%d,%d,%d] : runable\n", task[task_id].name, x, y, p );
[688]2328            else
2329            _printf(" - task %s on P[%d,%d,%d] : blocked\n", task[task_id].name, x, y, p );
2330        }
2331    }
2332    return 0;
2333}  // end _sys_tasks_status()
2334
2335
2336
[258]2337// Local Variables:
2338// tab-width: 4
2339// c-basic-offset: 4
2340// c-file-offsets:((innamespace . 0)(inline-open . 0))
2341// indent-tabs-mode: nil
2342// End:
2343// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
2344
Note: See TracBrowser for help on using the repository browser.