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

Last change on this file since 655 was 648, checked in by alain, 9 years ago

Introducing support for the new mechanism to start tasks.

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