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

Last change on this file since 680 was 670, checked in by alain, 9 years ago

Introduce the "shared" argument in the _sys_tty_alloc() function.

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