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

Last change on this file since 612 was 592, checked in by alain, 9 years ago

Introduce support for the new POSIX-like FAT32.

  • Property svn:executable set to *
File size: 61.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////////////////////////////////////////////////////////////////////////////
84//     Channel allocators for peripherals
85//     (TTY[0] is reserved for kernel)
86////////////////////////////////////////////////////////////////////////////
87
88__attribute__((section(".kdata")))
89unsigned int _tty_channel_allocator    = 1;
90
91__attribute__((section(".kdata")))
92unsigned int _tim_channel_allocator    = 0;
93
94__attribute__((section(".kdata")))
95unsigned int _cma_channel_allocator    = 0;
96
97__attribute__((section(".kdata")))
98unsigned int _nic_rx_channel_allocator = 0;
99
100__attribute__((section(".kdata")))
101unsigned int _nic_tx_channel_allocator = 0;
102
103////////////////////////////////////////////////////////////////////////////
104//     NIC_RX and NIC_TX chbuf arrays
105////////////////////////////////////////////////////////////////////////////
106
107__attribute__((section(".kdata")))
108nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
109
110__attribute__((section(".kdata")))
111nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
112
113////////////////////////////////////////////////////////////////////////////
114// FBF related chbuf descriptors array, indexed by the CMA channel index.
115// Physical addresses of these chbuf descriptors required for L2 cache sync.
116////////////////////////////////////////////////////////////////////////////
117
118__attribute__((section(".kdata")))
119fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
120
121__attribute__((section(".kdata")))
122unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
123
124////////////////////////////////////////////////////////////////////////////
125//    Initialize the syscall vector with syscall handlers
126// Note: This array must be synchronised with the define in file stdio.h
127////////////////////////////////////////////////////////////////////////////
128
129__attribute__((section(".kdata")))
130const void * _syscall_vector[64] = 
131{
132    &_sys_proc_xyp,                  /* 0x00 */
133    &_get_proctime,                  /* 0x01 */
134    &_sys_tty_write,                 /* 0x02 */
135    &_sys_tty_read,                  /* 0x03 */
136    &_sys_tty_alloc,                 /* 0x04 */
137    &_sys_tty_get_lock,              /* 0x05 */
138    &_sys_tty_release_lock,          /* 0x06 */
139    &_sys_heap_info,                 /* 0x07 */
140    &_sys_local_task_id,             /* 0x08 */
141    &_sys_global_task_id,            /* 0x09 */ 
142    &_sys_fbf_cma_alloc,             /* 0x0A */
143    &_sys_fbf_cma_start,             /* 0x0B */
144    &_sys_fbf_cma_display,           /* 0x0C */
145    &_sys_fbf_cma_stop,              /* 0x0D */
146    &_sys_task_exit,                 /* 0x0E */
147    &_sys_procs_number,              /* 0x0F */
148
149    &_sys_fbf_sync_write,            /* 0x10 */
150    &_sys_fbf_sync_read,             /* 0x11 */
151    &_sys_thread_id,                 /* 0x12 */
152    &_sys_ukn,                       /* 0x13 */
153    &_sys_tim_alloc,                 /* 0x14 */
154    &_sys_tim_start,                 /* 0x15 */ 
155    &_sys_tim_stop,                  /* 0x16 */
156    &_sys_ukn,                       /* 0x17 */
157    &_sys_ukn,                       /* 0x18 */   
158    &_sys_context_switch,            /* 0x19 */
159    &_sys_vseg_get_vbase,            /* 0x1A */
160    &_sys_vseg_get_length,           /* 0x1B */
161    &_sys_xy_from_ptr,               /* 0x1C */
162    &_sys_ukn,                       /* 0x1D */
163    &_sys_ukn,                       /* 0x1E */
164    &_sys_ukn,                       /* 0x1F */
165
166    &_fat_open,                      /* 0x20 */
167    &_fat_read,                      /* 0x21 */
168    &_fat_write,                     /* 0x22 */
169    &_fat_lseek,                     /* 0x23 */
170    &_fat_file_info,                 /* 0x24 */
171    &_fat_close,                     /* 0x25 */
172    &_fat_remove,                    /* 0x26 */
173    &_fat_rename,                    /* 0x27 */
174    &_fat_mkdir,                     /* 0x28 */
175    &_fat_list,                      /* 0x29 */
176    &_sys_ukn,                       /* 0x2A */
177    &_sys_ukn,                       /* 0x2B */
178    &_sys_ukn,                       /* 0x2C */
179    &_sys_ukn,                       /* 0x2D */
180    &_sys_ukn,                       /* 0x2E */
181    &_sys_ukn,                       /* 0x2F */
182
183    &_sys_nic_alloc,                 /* 0x30 */
184    &_sys_nic_start,                 /* 0x31 */
185    &_sys_nic_move,                  /* 0x32 */
186    &_sys_nic_stop,                  /* 0x33 */
187    &_sys_nic_stats,                 /* 0x34 */
188    &_sys_nic_clear,                 /* 0x35 */ 
189    &_sys_ukn,                       /* 0x36 */
190    &_sys_ukn,                       /* 0x37 */
191    &_sys_ukn,                       /* 0x38 */   
192    &_sys_ukn,                       /* 0x39 */
193    &_sys_ukn,                       /* 0x3A */
194    &_sys_coproc_completed,          /* 0x3B */
195    &_sys_coproc_alloc,              /* 0x3C */
196    &_sys_coproc_channel_init,       /* 0x3D */
197    &_sys_coproc_run,                /* 0x3E */
198    &_sys_coproc_release,            /* 0x3F */
199};
200
201
202//////////////////////////////////////////////////////////////////////////////
203//           Coprocessors related syscall handlers
204//////////////////////////////////////////////////////////////////////////////
205
206//////////////////////////////////////////////////
207int _sys_coproc_alloc( unsigned int   coproc_type,
208                       unsigned int*  coproc_info )
209{
210    // In this implementation, the allocation policy is constrained:
211    // the coprocessor must be in the same cluster as the calling task,
212    // and there is at most one coprocessor per cluster
213
214    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
215    mapping_cluster_t * cluster = _get_cluster_base(header);
216    mapping_periph_t  * periph  = _get_periph_base(header);
217
218    // get cluster coordinates and cluster global index
219    unsigned int procid     = _get_procid();
220    unsigned int x          = procid >> (Y_WIDTH + P_WIDTH);
221    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
222    unsigned int cluster_id = x * Y_SIZE + y;
223 
224    // search coprocessor in cluster
225    mapping_periph_t*  found = NULL;
226    unsigned int min   = cluster[cluster_id].periph_offset;
227    unsigned int max   = min + cluster[cluster_id].periphs;
228    unsigned int periph_id;
229    for ( periph_id = min ; periph_id < max ; periph_id++ )
230    {
231        if ( (periph[periph_id].type == PERIPH_TYPE_MWR) &&
232             (periph[periph_id].subtype == coproc_type) )
233        {
234            found = &periph[periph_id];
235            break;
236        }
237    } 
238
239    if ( found != NULL )
240    {
241        // get the lock (at most one coproc per cluster)
242        _simple_lock_acquire( &_coproc_lock[cluster_id] );
243
244        // register coproc characteristics in kernel arrays
245        _coproc_type[cluster_id] = coproc_type;
246        _coproc_info[cluster_id] = (found->arg0 & 0xFF)     |
247                                   (found->arg1 & 0xFF)<<8  |
248                                   (found->arg2 & 0xFF)<<16 |
249                                   (found->arg3 & 0xFF)<<24 ;
250
251        // returns coprocessor info
252        *coproc_info = _coproc_info[cluster_id];
253
254        // register coprocessor coordinates in task context
255        unsigned int cluster_xy = (x<<Y_WIDTH) + y;
256        _set_context_slot( CTX_COPROC_ID , cluster_xy );
257
258#if GIET_DEBUG_COPROC
259_printf("\n[GIET DEBUG COPROC] _sys_coproc_alloc() in cluster[%d,%d]\n"
260        "  coproc_info = %x / cluster_xy = %x\n",
261        x , y , *coproc_info , cluster_xy );
262#endif
263        return 0;
264    }
265    else
266    {
267         _printf("\n[GIET_ERROR] in _sys_coproc_alloc(): no coprocessor "
268                 " with type %d available in cluster[%d,%d]\n",
269                 coproc_type , x , y );
270        return -1;
271    }
272}  // end _sys_coproc_alloc()
273
274////////////////////////////////////////////////////////
275int _sys_coproc_release( unsigned int coproc_reg_index )
276{
277    // processor coordinates
278    unsigned int procid = _get_procid();
279    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
280    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
281    unsigned int p      = procid & ((1<<P_WIDTH)-1);
282   
283    // get coprocessor coordinates
284    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
285    if ( cluster_xy > 0xFF )
286    {
287         _printf("\n[GIET_ERROR] in _sys_coproc_release(): "
288                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
289                 x , y , p ); 
290         return -1;
291    }
292
293    unsigned int cx         = cluster_xy >> Y_WIDTH;
294    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
295    unsigned int cluster_id = cx * Y_SIZE + cy;
296    unsigned int info       = _coproc_info[cluster_id];
297    unsigned int nb_to      = info & 0xFF;
298    unsigned int nb_from    = (info>>8) & 0xFF;
299    unsigned int channel;
300
301    // stops coprocessor and communication channels
302    _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 0 );
303    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
304    {
305        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 );
306    }
307
308    // deallocates coprocessor coordinates in task context
309    _set_context_slot( CTX_COPROC_ID , 0xFFFFFFFF );
310
311    // release coprocessor lock
312    _simple_lock_release( &_coproc_lock[cluster_id] );
313
314#if GIET_DEBUG_COPROC
315_printf("\n[GIET DEBUG COPROC] _sys_coproc_release() in cluster[%d,%d]\n",
316        cx, cy );
317#endif
318
319    return 0;
320}  // end _sys_coproc_release()
321
322//////////////////////////////////////////////////////////////
323int _sys_coproc_channel_init( unsigned int            channel,
324                              giet_coproc_channel_t*  desc )
325{
326    // processor coordinates
327    unsigned int procid = _get_procid();
328    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
329    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
330    unsigned int p      = procid & ((1<<P_WIDTH)-1);
331   
332    // get coprocessor coordinates
333    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
334    if ( cluster_xy > 0xFF )
335    {
336         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
337                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
338                 x , y , p ); 
339         return -1;
340    }
341
342    // check channel mode
343    unsigned mode = desc->channel_mode;
344    if ( (mode != MODE_MWMR) && 
345         (mode != MODE_DMA_IRQ) && 
346         (mode != MODE_DMA_NO_IRQ) )
347    {
348         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
349                 " illegal mode\n");
350         return -1;
351    }
352
353    // get memory buffer size
354    unsigned int size = desc->buffer_size;
355 
356    // physical addresses
357    unsigned long long buffer_paddr;
358    unsigned int       buffer_lsb;
359    unsigned int       buffer_msb;
360    unsigned long long mwmr_paddr = 0;
361    unsigned int       mwmr_lsb;
362    unsigned int       mwmr_msb;
363    unsigned long long lock_paddr = 0;
364    unsigned int       lock_lsb;
365    unsigned int       lock_msb;
366
367    unsigned int       flags;     // unused
368
369    // compute memory buffer physical address
370    buffer_paddr = _v2p_translate( desc->buffer_vaddr , &flags );
371    buffer_lsb   = (unsigned int)buffer_paddr;
372    buffer_msb   = (unsigned int)(buffer_paddr>>32); 
373
374    // call MWMR_DMA driver
375    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MODE, mode ); 
376    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_SIZE, size ); 
377    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_LSB, buffer_lsb ); 
378    _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_BUFFER_MSB, buffer_msb ); 
379                       
380    if ( mode == MODE_MWMR )
381    {
382        // compute MWMR descriptor physical address
383        mwmr_paddr = _v2p_translate( desc->mwmr_vaddr , &flags );
384        mwmr_lsb = (unsigned int)mwmr_paddr;
385        mwmr_msb = (unsigned int)(mwmr_paddr>>32); 
386
387        // call MWMR_DMA driver
388        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_LSB, mwmr_lsb ); 
389        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_MWMR_MSB, mwmr_msb ); 
390
391        // compute lock physical address
392        lock_paddr = _v2p_translate( desc->lock_vaddr , &flags );
393        lock_lsb = (unsigned int)lock_paddr;
394        lock_msb = (unsigned int)(lock_paddr>>32); 
395
396        // call MWMR_DMA driver
397        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_LSB, lock_lsb ); 
398        _mwr_set_channel_register( cluster_xy, channel, MWR_CHANNEL_LOCK_MSB, lock_msb ); 
399    }
400
401#if GIET_DEBUG_COPROC
402_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_init() for coproc[%d,%d]\n"
403        " channel =  %d / mode = %d / buffer_size = %d\n"
404        " buffer_paddr = %l / mwmr_paddr = %l / lock_paddr = %l\n",
405        x , y , channel , mode , size ,
406        buffer_paddr, mwmr_paddr, lock_paddr );
407#endif
408       
409    return 0;
410} // end _sys_coproc_channel_init()
411
412////////////////////////////////////////////////////
413int _sys_coproc_run( unsigned int coproc_reg_index )
414{
415    // processor coordinates
416    unsigned int procid = _get_procid();
417    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
418    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
419    unsigned int p      = procid & ((1<<P_WIDTH)-1);
420   
421    // get coprocessor coordinates
422    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
423    if ( cluster_xy > 0xFF )
424    {
425         _printf("\n[GIET_ERROR] in _sys_coproc_run(): "
426                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
427                 x , y , p ); 
428         return -1;
429    }
430
431    unsigned int cx         = cluster_xy >> Y_WIDTH;
432    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
433    unsigned int cluster_id = cx * Y_SIZE + cy;
434    unsigned int info       = _coproc_info[cluster_id];
435    unsigned int nb_to      = info & 0xFF;
436    unsigned int nb_from    = (info>>8) & 0xFF;
437    unsigned int mode       = 0xFFFFFFFF;
438    unsigned int channel;
439
440    // register coprocessor running mode
441    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
442    {
443        unsigned int temp;
444        temp = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_MODE );
445
446        if ( mode == 0xFFFFFFFF ) 
447        {
448            mode = temp;
449        }
450        else if ( temp != mode )
451        {
452            _printf("\n[GIET_ERROR] P[%d,%d,%d] in _sys_coproc_run() for coprocessor[%d,%d]\n"
453                    "  all channels don't have the same mode\n", x , y , p , cx , cy );
454            return -1;
455        }
456    }
457    _coproc_mode[cluster_id] = mode;
458
459    // start all communication channels
460    for ( channel = 0 ; channel < (nb_from + nb_to) ; channel++ )
461    {
462        _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 1 );
463    }
464
465    //////////////////////////////////////////////////////////////////////////
466    if ( (mode == MODE_MWMR) || (mode == MODE_DMA_NO_IRQ) )  // no descheduling
467    {
468        // start coprocessor
469        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
470
471#if GIET_DEBUG_COPROC
472if ( mode == MODE_MWMR )
473_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
474        "   MODE_MWMR at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
475else
476_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
477        "   MODE_DMA_NO_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
478#endif
479
480        return 0;
481    }
482    ///////////////////////////////////////////////////////////////////////////
483    else                                // mode == MODE_DMA_IRQ => descheduling
484    {
485        // set _coproc_gtid
486        unsigned int ltid = _get_current_task_id();
487        _coproc_gtid[cluster_id] = (procid<<16) + ltid;
488
489        // enters critical section
490        unsigned int save_sr;
491        _it_disable( &save_sr ); 
492
493        // reset runnable
494        _set_task_slot( x, y, p, ltid, CTX_RUN_ID, 0 ); 
495
496        // start coprocessor
497        _mwr_set_coproc_register( cluster_xy , coproc_reg_index , 1 );
498
499#if GIET_DEBUG_COPROC
500_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] starts coprocessor[%d,%d]\n"
501        "   MODE_DMA_IRQ at cycle %d\n", x , y , p , cx , cy , _get_proctime() );
502#endif
503
504        // deschedule task
505        _ctx_switch(); 
506
507#if GIET_DEBUG_COPROC
508_printf("\n[GIET DEBUG COPROC] _sys_coproc_run() P[%d,%d,%d] resume\n"
509        "  coprocessor[%d,%d] completion at cycle %d\n", 
510        x , y , p , cx , cy , _get_proctime() );
511#endif
512
513        // restore SR
514        _it_restore( &save_sr );
515
516        // return error computed by mwr_isr()
517        return _coproc_error[cluster_id];
518    } 
519} // end _sys_coproc_run()
520
521///////////////////////////
522int _sys_coproc_completed()
523{
524    // processor coordinates
525    unsigned int procid = _get_procid();
526    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
527    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
528    unsigned int p      = procid & ((1<<P_WIDTH)-1);
529   
530    // get coprocessor coordinates
531    unsigned int cluster_xy = _get_context_slot( CTX_COPROC_ID );
532    if ( cluster_xy > 0xFF )
533    {
534         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
535                 "no coprocessor allocated to task running on P[%d,%d,%d]\n",
536                 x , y , p ); 
537         return -1;
538    }
539
540    unsigned int cx         = cluster_xy >> Y_WIDTH;
541    unsigned int cy         = cluster_xy & ((1<<Y_WIDTH)-1);
542    unsigned int cluster_id = cx * Y_SIZE + cy;
543    unsigned int mode       = _coproc_mode[cluster_id];
544
545    // analyse possible errors
546    if ( mode == MODE_DMA_NO_IRQ )
547    {
548        unsigned int info       = _coproc_info[cluster_id];
549        unsigned int nb_to      = info & 0xFF;
550        unsigned int nb_from    = (info>>8) & 0xFF;
551        unsigned int error      = 0;
552        unsigned int channel;
553        unsigned int status;
554
555        // get status for all channels, and signal all reported errors
556        for ( channel = 0 ; channel < (nb_to +nb_from) ; channel++ )
557        {
558            do
559            {
560                status = _mwr_get_channel_register( cluster_xy , channel , MWR_CHANNEL_STATUS );
561                if ( status == MWR_CHANNEL_ERROR_DATA )
562                {
563                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
564                            " / channel %d / DATA_ERROR\n", channel );
565                    error = 1;
566                    break;
567                }
568                else if ( status == MWR_CHANNEL_ERROR_LOCK )
569                {
570                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
571                            " / channel %d / LOCK_ERROR\n", channel );
572                    error = 1;
573                    break;
574                }
575                else if ( status == MWR_CHANNEL_ERROR_DESC )
576                {
577                    _printf("\n[GIET_ERROR] in _sys_coproc_completed()"
578                            " / channel %d / DESC_ERROR\n", channel );
579                    error = 1;
580                    break;
581                }
582            } while ( status == MWR_CHANNEL_BUSY );
583
584            // reset channel
585            _mwr_set_channel_register( cluster_xy , channel , MWR_CHANNEL_RUNNING , 0 ); 
586
587        }  // end for channels
588
589#if GIET_DEBUG_COPROC
590_printf("\n[GIET DEBUG COPROC] _sys_coproc_completed() for coprocessor[%d,%d] error = %d\n", 
591        cx , cy , error );
592#endif
593
594        return error;
595    }
596    else  // mode == MODE_MWMR or MODE_DMA_IRQ
597    {
598        _printf("\n[GIET ERROR] sys_coproc_completed() should not be called for "
599                "coprocessor[%d,%d] running in MODE_MWMR or MODE_DMA_IRQ\n", cx , cy );
600        return 1;
601    }
602} // end _sys_coproc_completed()
603
604
605//////////////////////////////////////////////////////////////////////////////
606//             TTY related syscall handlers
607//////////////////////////////////////////////////////////////////////////////
608
609////////////////////
610int _sys_tty_alloc()
611{
612    // get a new TTY terminal index
613    unsigned int channel = _atomic_increment( &_tty_channel_allocator, 1 );
614
615    if ( channel >= NB_TTY_CHANNELS )
616    {
617        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n");
618        return -1;
619    }
620    else
621    {
622    }
623
624    // allocate a WTI mailbox to the calling proc if external IRQ
625    unsigned int unused;
626    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &unused ); 
627   
628    // update calling task index
629    _set_context_slot( CTX_TTY_ID, channel );
630
631    return 0;
632}
633
634/////////////////////////////////////////////////
635int _sys_tty_write( const char*  buffer,   
636                    unsigned int length,    // number of characters
637                    unsigned int channel)   // channel index
638{
639    unsigned int  nwritten;
640
641    // compute and check tty channel
642    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
643    if( channel >= NB_TTY_CHANNELS ) return -1;
644
645    // write string to TTY channel
646    for (nwritten = 0; nwritten < length; nwritten++) 
647    {
648        // check tty's status
649        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
650
651        // write one byte
652        if (buffer[nwritten] == '\n') 
653        {
654            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
655        }
656        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
657    }
658   
659    return nwritten;
660}
661
662////////////////////////////////////////////////
663int _sys_tty_read( char*        buffer, 
664                   unsigned int length,    // unused
665                   unsigned int channel)   // channel index
666{
667    // compute and check tty channel
668    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
669    if( channel >= NB_TTY_CHANNELS ) return -1;
670
671    // read one character from TTY channel
672    if (_tty_rx_full[channel] == 0) 
673    {
674        return 0;
675    }
676    else 
677    {
678        *buffer = _tty_rx_buf[channel];
679        _tty_rx_full[channel] = 0;
680        return 1;
681    }
682}
683
684///////////////////////////////////////////
685int _sys_tty_get_lock( unsigned int   channel,       // unused
686                       unsigned int * save_sr_ptr )
687{
688    // check tty channel
689    if( channel != 0 )  return 1;
690
691    _it_disable( save_sr_ptr );
692    _sqt_lock_acquire( &_tty0_sqt_lock );
693    return 0;
694}
695
696///////////////////////////////////////////////
697int _sys_tty_release_lock( unsigned int   channel,
698                           unsigned int * save_sr_ptr )
699{
700    // check tty channel
701    if( channel != 0 )  return 1;
702
703    _sqt_lock_release( &_tty0_sqt_lock );
704    _it_restore( save_sr_ptr );
705    return 0;
706}
707
708//////////////////////////////////////////////////////////////////////////////
709//             TIM related syscall handlers
710//////////////////////////////////////////////////////////////////////////////
711
712////////////////////
713int _sys_tim_alloc()
714{
715    // get a new timer index
716    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
717
718    if ( channel >= NB_TIM_CHANNELS )
719    {
720        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
721        return -1;
722    }
723    else
724    {
725        _set_context_slot( CTX_TIM_ID, channel );
726        return 0;
727    }
728}
729
730/////////////////////////////////////////
731int _sys_tim_start( unsigned int period )
732{
733    // get timer index
734    unsigned int channel = _get_context_slot( CTX_TIM_ID );
735    if ( channel >= NB_TIM_CHANNELS )
736    {
737        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
738        return -1;
739    }
740
741    // start timer
742    _timer_start( channel, period );
743
744    return 0;
745}
746
747///////////////////
748int _sys_tim_stop()
749{
750    // get timer index
751    unsigned int channel = _get_context_slot( CTX_TIM_ID );
752    if ( channel >= NB_TIM_CHANNELS )
753    {
754        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
755        return -1;
756    }
757
758    // stop timer
759    _timer_stop( channel );
760
761    return 0;
762}
763
764//////////////////////////////////////////////////////////////////////////////
765//             NIC related syscall handlers
766//////////////////////////////////////////////////////////////////////////////
767
768#define NIC_CONTAINER_SIZE 4096
769
770////////////////////////////////////////
771int _sys_nic_alloc( unsigned int is_rx,
772                    unsigned int xmax,
773                    unsigned int ymax )
774{
775    // check xmax / ymax parameters
776    if ( xmax > X_SIZE )
777    {
778        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
779        return -1;
780    }
781    if ( ymax > Y_SIZE )
782    {
783        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
784        return -1;
785    }
786
787    // get a NIC_RX or NIC_TX channel index
788    unsigned int nic_channel;
789    unsigned int cma_channel;
790
791    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
792    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
793
794    if ( (nic_channel >= NB_NIC_CHANNELS) )
795    {
796        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
797        return -1;
798    }
799
800    // get a CMA channel index
801    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
802
803    if ( cma_channel >= NB_CMA_CHANNELS )
804    {
805        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
806        return -1;
807    }
808
809#if GIET_DEBUG_NIC
810unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
811_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
812        "  nic_channel = %d / cma_channel = %d\n",
813        thread , _get_proctime() , nic_channel , cma_channel );
814#endif
815
816    // register nic_index and cma_index in task context
817    if ( is_rx )
818    {
819        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
820        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
821    }
822    else
823    {
824        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
825        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
826    }
827
828    // physical addresses to be registered in the CMA registers
829    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
830    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
831
832    // allocate one kernel container per cluster in the (xmax / ymax) mesh
833    unsigned int        cx;                 // cluster X coordinate
834    unsigned int        cy;                 // cluster Y coordinate
835    unsigned int        index;              // container index in chbuf
836    unsigned int        vaddr;              // virtual address
837    unsigned long long  cont_paddr;         // container physical address
838
839    unsigned int        flags;              // for _v2p_translate()
840
841    for ( cx = 0 ; cx < xmax ; cx++ )
842    {
843        for ( cy = 0 ; cy < ymax ; cy++ )
844        {
845            // compute index in chbuf
846            index = (cx * ymax) + cy; 
847
848            // allocate the kernel container
849            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
850
851            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
852            {
853                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
854                        " in cluster[%d,%d]\n", cx, cy );
855                return -1;
856            }
857
858            // compute container physical address
859            cont_paddr = _v2p_translate( vaddr , &flags );
860
861            // initialize chbuf entry
862            if ( is_rx ) _nic_rx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
863            else         _nic_tx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
864
865#if GIET_DEBUG_NIC
866_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()"
867        " allocates container in cluster[%d,%d]\n"
868        "  vaddr = %x / paddr = %l\n",
869        thread , cx , cy , vaddr , cont_paddr );
870#endif
871        }
872    }
873
874    // complete kernel chbuf initialisation
875    if ( is_rx )
876    {
877        _nic_rx_chbuf[nic_channel].xmax = xmax;
878        _nic_rx_chbuf[nic_channel].ymax = ymax;
879    }
880    else
881    {
882        _nic_tx_chbuf[nic_channel].xmax = xmax;
883        _nic_tx_chbuf[nic_channel].ymax = ymax;
884    }
885
886    // compute the NIC chbuf descriptor physical address
887    unsigned int offset;
888    if ( is_rx ) offset = 0x4000;
889    else         offset = 0x4080;
890    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
891                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
892
893#if GIET_DEBUG_NIC
894_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
895        thread , nic_chbuf_pbase );
896#endif
897
898    // compute the kernel chbuf descriptor physical address
899    if ( is_rx ) vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
900    else         vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
901
902    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
903
904#if GIET_DEBUG_NIC
905_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
906        "  vaddr = %x / paddr = %l\n",
907        thread , vaddr , ker_chbuf_pbase );
908#endif
909
910    // sync the kernel chbuf in L2 after write in L2
911    _mmc_sync( ker_chbuf_pbase, sizeof( nic_chbuf_t ) );
912
913    // initializes CMA registers defining the source & destination chbufs
914    if ( is_rx )               // NIC to kernel
915    {
916        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
917        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
918        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
919        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
920        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
921        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
922    }
923    else                      // kernel to NIC
924    {
925        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
926        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
927        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
928        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
929        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
930        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
931    }
932
933#if GIET_DEBUG_NIC
934_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
935        thread, _get_proctime() );
936#endif
937
938    return nic_channel;
939} // end _sys_nic_alloc()
940
941
942////////////////////////////////////////
943int _sys_nic_start( unsigned int is_rx,
944                    unsigned int channel )
945{
946    unsigned int nic_channel;
947    unsigned int cma_channel;
948
949    // get NIC channel index and CMA channel index from task context
950    if ( is_rx )
951    {
952        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
953        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
954    }
955    else
956    {
957        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
958        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
959    }
960
961#if GIET_DEBUG_NIC
962unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
963_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d\n"
964        "  get NIC channel = %d / CMA channel = %d\n",
965        thread, _get_proctime(), nic_channel, cma_channel );
966#endif
967
968    // check NIC and CMA channels index
969    if ( nic_channel != channel )
970    {
971        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
972        return -1;
973    }
974    if ( cma_channel >= NB_CMA_CHANNELS )
975    {
976        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
977        return -1;
978    }
979
980    // start CMA transfer
981    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
982    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
983    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
984
985    // activates NIC channel
986    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 ); 
987
988#if GIET_DEBUG_NIC
989_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
990        thread , _get_proctime() );
991#endif
992
993    return 0;
994}  // end _sys_nic_start()
995
996
997//////////////////////////////////////
998int _sys_nic_move( unsigned int is_rx,
999                   unsigned int channel,
1000                   void*        buffer )
1001{
1002
1003#if GIET_DEBUG_NIC
1004unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
1005_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
1006        thread , _get_proctime() );
1007#endif
1008
1009    // check NIC channel index
1010    if ( channel >= NB_NIC_CHANNELS )
1011    {
1012        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
1013        return -1;
1014    }
1015
1016    // get kernel chbuf virtual address
1017    nic_chbuf_t* chbuf;
1018    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
1019    else          chbuf = &_nic_tx_chbuf[channel];
1020
1021    // get xmax / ymax parameters
1022    unsigned int xmax = chbuf->xmax;
1023    unsigned int ymax = chbuf->ymax;
1024
1025    // get cluster coordinates for the processor running the calling task
1026    unsigned int  procid = _get_procid();
1027    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
1028    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1029   
1030    // check processor coordinates / (xmax,ymax)
1031    if ( cx >= xmax )
1032    {
1033        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
1034                " / xmax = %d\n", cx , xmax );
1035        return -1;
1036    }
1037    if ( cy >= ymax )
1038    {
1039        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
1040                " / ymax = %d\n", cy , ymax );
1041        return -1;
1042    }
1043   
1044    unsigned long long user_buffer_paddr;    // user buffer physical address
1045    unsigned long long kernel_buffer_paddr;  // kernel buffer physical address
1046    unsigned long long kernel_chbuf_paddr;   // kernel chbuf physical address
1047    unsigned long long buffer_descriptor;    // kernel buffer descriptor
1048    unsigned long long buffer_desc_paddr;    // kernel buffer descriptor paddr
1049    unsigned int       index;                // kernel buffer index in chbuf
1050    unsigned int       flags;                // for _v2P_translate
1051
1052    // Compute user buffer physical address and check access rights
1053    user_buffer_paddr = _v2p_translate( (unsigned int)buffer , &flags );
1054
1055    if ( (flags & PTE_U) == 0 )
1056    {
1057        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
1058        return -1;
1059    }
1060
1061#if GIET_DEBUG_NIC
1062_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
1063        thread, user_buffer_paddr );
1064#endif
1065
1066    // compute kernel chbuf physical address (required for sync)
1067    kernel_chbuf_paddr = _v2p_translate( (unsigned int)chbuf , &flags );
1068
1069    // poll local kernel container status until success
1070    while ( 1 )
1071    {
1072        // compute buffer index and buffer descriptor paddr
1073        index = (ymax * cx) + cy;
1074        buffer_desc_paddr = kernel_chbuf_paddr + (index<<6);
1075
1076        // inval buffer descriptor in L2 before read in L2
1077        _mmc_inval( buffer_desc_paddr , 8 );
1078        buffer_descriptor = chbuf->buffer[index].desc;
1079
1080#if GIET_DEBUG_NIC
1081_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read buf_desc %d at cycle %d\n"
1082        "  paddr = %l / buffer descriptor = %l\n",
1083        thread, index, _get_proctime(), buffer_desc_paddr, buffer_descriptor );
1084#endif
1085
1086        // test buffer status and break if found
1087        if ( ( is_rx != 0 ) && (buffer_descriptor >> 63) == 1 )  break;
1088        if ( ( is_rx == 0 ) && (buffer_descriptor >> 63) == 0 )  break;
1089    }
1090
1091    // compute kernel buffer physical address
1092    kernel_buffer_paddr = buffer_descriptor & 0x0000FFFFFFFFFFFFULL;
1093   
1094    // move one container
1095    if ( is_rx )              // RX transfer
1096    {
1097        // inval kernel buffer in L2 before read in L2
1098        _mmc_inval( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
1099
1100        // transfer data from kernel buffer to user buffer
1101        _physical_memcpy( user_buffer_paddr, 
1102                          kernel_buffer_paddr, 
1103                          NIC_CONTAINER_SIZE );
1104#if GIET_DEBUG_NIC
1105_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
1106        " to user buffer %l at cycle %d\n",
1107        thread , kernel_buffer_paddr , user_buffer_paddr , _get_proctime() );
1108#endif
1109
1110    }
1111    else                      // TX transfer
1112    {
1113        // transfer data from user buffer to kernel buffer
1114        _physical_memcpy( kernel_buffer_paddr, 
1115                          user_buffer_paddr, 
1116                          NIC_CONTAINER_SIZE );
1117
1118        // sync kernel buffer in L2 after write in L2
1119        _mmc_sync( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
1120
1121#if GIET_DEBUG_NIC
1122_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
1123        "user buffer %l to kernel buffer %l at cycle %d\n",
1124        thread , user_buffer_paddr , kernel_buffer_paddr , _get_proctime() );
1125#endif
1126
1127    }
1128
1129    // update kernel chbuf status
1130    if ( is_rx ) chbuf->buffer[index].desc = kernel_buffer_paddr & 0x0000FFFFFFFFFFFFULL;
1131    else         chbuf->buffer[index].desc = kernel_buffer_paddr | 0x8000000000000000ULL;
1132
1133    // sync kernel chbuf in L2 after write in L2
1134    _mmc_sync( kernel_chbuf_paddr + (index<<6) , 8 );
1135
1136#if GIET_DEBUG_NIC
1137_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
1138        thread , index , _get_proctime() );
1139#endif
1140
1141    return 0;
1142} // end _sys_nic_move()
1143
1144
1145////////////////////////////////////////
1146int _sys_nic_stop( unsigned int is_rx,
1147                   unsigned int channel )
1148{
1149    unsigned int nic_channel;
1150    unsigned int cma_channel;
1151
1152    // get NIC channel index and CMA channel index
1153    if ( is_rx )
1154    {
1155        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1156        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
1157    }
1158    else
1159    {
1160        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1161        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1162    }
1163
1164    // check NIC and CMA channels index
1165    if ( nic_channel != channel )
1166    {
1167        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
1168        return -1;
1169    }
1170    if ( cma_channel >= NB_CMA_CHANNELS )
1171    {
1172        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
1173        return -1;
1174    }
1175
1176    // desactivates the NIC channel
1177    _nic_channel_stop( nic_channel, is_rx );
1178
1179    // desactivates the CMA channel
1180    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
1181
1182    return 0;
1183}  // end _sys_nic_stop()
1184
1185////////////////////////////////////////
1186int _sys_nic_clear( unsigned int is_rx,
1187                    unsigned int channel )
1188{
1189    unsigned int nic_channel;
1190
1191    // get NIC channel
1192    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1193    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1194
1195    if ( nic_channel != channel )
1196    {
1197        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
1198        return -1;
1199    }
1200
1201    if ( is_rx )
1202    {
1203        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
1204        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
1205        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
1206        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
1207        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
1208        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
1209        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
1210        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
1211        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
1212    } 
1213    else
1214    {
1215        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
1216        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
1217        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
1218        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
1219        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
1220        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
1221        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
1222    }
1223    return 0;
1224}  // en _sys_nic_clear()
1225
1226////////////////////////////////////////
1227int _sys_nic_stats( unsigned int is_rx,
1228                    unsigned int channel )
1229{
1230    unsigned int nic_channel;
1231
1232    // get NIC channel
1233    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1234    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1235
1236    if ( nic_channel != channel )
1237    {
1238        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
1239        return -1;
1240    }
1241
1242    if ( is_rx )
1243    {
1244        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
1245        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
1246        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
1247        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
1248        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
1249        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
1250        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
1251        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
1252
1253        _printf("\n### Network Controller RX Statistics ###\n"
1254                "- packets received : %d\n"
1255                "- too small        : %d\n"
1256                "- too big          : %d\n"
1257                "- fifo full        : %d\n" 
1258                "- crc fail         : %d\n" 
1259                "- dst mac fail     : %d\n" 
1260                "- channel full     : %d\n" 
1261                "- broadcast        : %d\n",
1262                received,
1263                too_small,
1264                too_big,
1265                fifo_full,
1266                crc_fail,
1267                dst_fail,
1268                ch_full,
1269                broadcast );
1270    } 
1271    else
1272    {
1273        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
1274        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
1275        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
1276        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
1277        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
1278        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
1279
1280        _printf("\n### Network Controller TX Statistics ###\n"
1281                "- packets received : %d\n"
1282                "- too small        : %d\n"
1283                "- too big          : %d\n"
1284                "- src mac fail     : %d\n" 
1285                "- bypass           : %d\n" 
1286                "- broadcast        : %d\n",
1287                received,
1288                too_big,
1289                too_small,
1290                src_fail,
1291                bypass,
1292                broadcast );
1293    }
1294    return 0;
1295}  // end _sys_nic_stats()
1296
1297/////////////////////////////////////////////////////////////////////////////////////////
1298//    FBF related syscall handlers
1299/////////////////////////////////////////////////////////////////////////////////////////
1300
1301/////////////////////////////////////////////
1302int _sys_fbf_sync_write( unsigned int offset,
1303                         void*        buffer,
1304                         unsigned int length )
1305{
1306    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1307    memcpy( fbf_address, buffer, length);
1308
1309    return 0;
1310}
1311
1312/////////////////////////////////////////////
1313int _sys_fbf_sync_read(  unsigned int offset,
1314                         void*        buffer,
1315                         unsigned int length )
1316{
1317    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1318    memcpy( buffer, fbf_address, length);
1319
1320    return 0;
1321}
1322
1323////////////////////////
1324int _sys_fbf_cma_alloc()
1325{
1326   // get a new CMA channel index
1327    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
1328
1329    if ( channel >= NB_CMA_CHANNELS )
1330    {
1331        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
1332        return -1;
1333    }
1334    else
1335    {
1336        _set_context_slot( CTX_CMA_FB_ID, channel );
1337        return 0;
1338    }
1339} // end sys_fbf_cma_alloc()
1340
1341////////////////////////////////////////////
1342int _sys_fbf_cma_start( void*        vbase0, 
1343                        void*        vbase1, 
1344                        unsigned int length ) 
1345{
1346#if NB_CMA_CHANNELS > 0
1347
1348    unsigned int       vaddr;           // virtual address
1349    unsigned int       flags;           // for _v2p_translate()
1350
1351    // get channel index
1352    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1353
1354    if ( channel >= NB_CMA_CHANNELS )
1355    {
1356        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
1357        return -1;
1358    }
1359
1360#if GIET_DEBUG_FBF_CMA
1361_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_start()\n"
1362        " - channel      = %d\n"
1363        " - buf0   vbase = %x\n"
1364        " - buf1   vbase = %x\n"
1365        " - buffer size  = %x\n",
1366        channel,
1367        (unsigned int)vbase0,
1368        (unsigned int)vbase1,
1369        length );
1370#endif
1371
1372    // checking user buffers virtual addresses and length alignment
1373    if ( ((unsigned int)vbase0 & 0x3) || 
1374         ((unsigned int)vbase1 & 0x3) || 
1375         (length & 0x3) ) 
1376    {
1377        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer not aligned\n");
1378        return -1;
1379    }
1380
1381    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
1382    vaddr = (unsigned int)SEG_FBF_BASE;
1383    _fbf_chbuf[channel].fbf.desc = _v2p_translate( vaddr , &flags );
1384
1385    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
1386    vaddr = (unsigned int)vbase0;
1387    _fbf_chbuf[channel].buf0.desc = _v2p_translate( vaddr , &flags );
1388
1389    if ((flags & PTE_U) == 0) 
1390    {
1391        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf0 not in user space\n");
1392        return -1;
1393    }
1394
1395    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
1396    vaddr = (unsigned int)vbase1;
1397    _fbf_chbuf[channel].buf1.desc = _v2p_translate( vaddr , &flags );
1398
1399    if ((flags & PTE_U) == 0) 
1400    {
1401        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf1 not in user space\n");
1402        return -1;
1403    }
1404
1405    // initializes buffer length
1406    _fbf_chbuf[channel].length = length;
1407
1408    // Compute and register physical adress of the fbf_chbuf descriptor
1409    vaddr = (unsigned int)&_fbf_chbuf[channel];
1410    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
1411 
1412    if ( USE_IOB )
1413    {
1414        // SYNC request for fbf_chbuf descriptor
1415        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
1416    }
1417
1418#if GIET_DEBUG_FBF_CMA
1419_printf(" - fbf    pbase = %l\n"
1420        " - buf0   pbase = %l\n"
1421        " - buf1   pbase = %l\n"
1422        " - chbuf  pbase = %l\n",
1423        _fbf_chbuf[channel].fbf.desc,
1424        _fbf_chbuf[channel].buf0.desc,
1425        _fbf_chbuf[channel].buf1.desc,
1426        _fbf_chbuf_paddr[channel] );
1427#endif
1428
1429    // start CMA transfer
1430    unsigned long long paddr = _fbf_chbuf_paddr[channel];
1431    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
1432    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
1433    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 128;
1434    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
1435
1436    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
1437    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
1438    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
1439    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
1440    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
1441    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
1442    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
1443    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
1444    _cma_set_register( channel, CHBUF_RUN      , 1 );
1445
1446    return 0;
1447
1448#else
1449
1450    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1451    return -1;
1452
1453#endif
1454} // end _sys_fbf_cma_start()
1455
1456/////////////////////////////////////////////////////
1457int _sys_fbf_cma_display( unsigned int buffer_index )
1458{
1459#if NB_CMA_CHANNELS > 0
1460
1461    volatile unsigned int full = 1;
1462
1463    // get channel index
1464    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1465
1466    if ( channel >= NB_CMA_CHANNELS )
1467    {
1468        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1469                "CMA channel index too large\n");
1470        return -1;
1471    }
1472
1473    // get fbf_chbuf descriptor pointer
1474    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1475
1476#if GIET_DEBUG_FBF_CMA
1477_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
1478        " - cma channel     = %d\n"
1479        " - buffer index    = %d\n"
1480        " - buf0_desc value = %l\n"
1481        " - buf1_desc value = %l\n"
1482        " - fbf_desc  value = %l\n",
1483        channel , buffer_index,
1484        _fbf_chbuf[channel].buf0.desc,
1485        _fbf_chbuf[channel].buf1.desc,
1486        _fbf_chbuf[channel].fbf.desc );
1487#endif
1488
1489    if ( buffer_index == 0 )    // user buffer 0
1490    {
1491        // INVAL L1 and L2 cache copies of user buffer descriptor,
1492        // because it has been modified in RAM by the CMA component
1493        _dcache_buf_invalidate( (unsigned int)pdesc , sizeof(buffer_descriptor_t) );
1494        _mmc_inval( _fbf_chbuf_paddr[channel] , sizeof(buffer_descriptor_t) );
1495
1496        // waiting user buffer released by the CMA component)
1497        while ( full )
1498        { 
1499            full = (unsigned int)(pdesc->buf0.desc >> 63);
1500        }
1501
1502        // SYNC request for the user buffer, because
1503        // it will be read from XRAM by the CMA component
1504        _mmc_sync( pdesc->buf0.desc , pdesc->length );
1505
1506        // set user buffer status
1507        pdesc->buf0.desc = pdesc->buf0.desc | 0x8000000000000000ULL;
1508
1509        // reset fbf buffer status
1510        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
1511
1512        // SYNC request, because these buffer descriptors
1513        // will be read from XRAM by the CMA component
1514        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
1515    }
1516    else                        // user buffer 1
1517    {
1518        // INVAL L1 and L2 cache copies of user buffer descriptor,
1519        // because it has been modified in RAM by the CMA component
1520        _dcache_buf_invalidate( (unsigned int)pdesc + 64, sizeof(buffer_descriptor_t) );
1521        _mmc_inval( _fbf_chbuf_paddr[channel] + 64, sizeof(buffer_descriptor_t) );
1522
1523        // waiting user buffer released by the CMA component)
1524        while ( full )
1525        { 
1526            full = (unsigned int)(pdesc->buf1.desc >> 63);
1527        }
1528
1529        // SYNC request for the user buffer, because
1530        // it will be read from XRAM by the CMA component
1531        _mmc_sync( pdesc->buf1.desc , pdesc->length );
1532
1533        // set user buffer status
1534        pdesc->buf1.desc = pdesc->buf1.desc | 0x8000000000000000ULL;
1535
1536        // reset fbf buffer status
1537        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
1538
1539        // SYNC request, because these buffer descriptors
1540        // will be read from XRAM by the CMA component
1541        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
1542    }
1543
1544#if GIET_DEBUG_FBF_CMA
1545_printf("\n[FBF_CMA DEBUG] exit _sys_fb_cma_display()\n"
1546        " - buf0_desc value = %l\n"
1547        " - buf1_desc value = %l\n"
1548        " - fbf_desc  value = %l\n",
1549        _fbf_chbuf[channel].buf0.desc,
1550        _fbf_chbuf[channel].buf1.desc,
1551        _fbf_chbuf[channel].fbf.desc );
1552#endif
1553
1554    return 0;
1555
1556#else
1557
1558    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1559    return -1;
1560
1561#endif
1562} // end _sys_fbf_cma_display()
1563
1564
1565///////////////////////
1566int _sys_fbf_cma_stop()
1567{
1568#if NB_CMA_CHANNELS > 0
1569
1570    // get channel index
1571    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1572
1573    if ( channel >= NB_CMA_CHANNELS )
1574    {
1575        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
1576        return -1;
1577    }
1578
1579    // Desactivate CMA channel
1580    _cma_set_register( channel, CHBUF_RUN, 0 );
1581
1582    return 0;
1583
1584#else
1585
1586    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
1587    return -1;
1588
1589#endif
1590} // end _sys_fbf_cma_stop()
1591
1592
1593//////////////////////////////////////////////////////////////////////////////
1594//           Miscelaneous syscall handlers
1595//////////////////////////////////////////////////////////////////////////////
1596
1597///////////////
1598int _sys_ukn() 
1599{
1600    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
1601    return -1;
1602}
1603
1604////////////////////////////////////
1605int _sys_proc_xyp( unsigned int* x,
1606                   unsigned int* y,
1607                   unsigned int* p )
1608{
1609    unsigned int gpid = _get_procid();  // global processor index from CPO register
1610
1611    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
1612    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1613    *p = gpid & ((1<<P_WIDTH)-1);
1614
1615    return 0;
1616}
1617
1618//////////////////////////////////
1619int _sys_task_exit( char* string ) 
1620{
1621    unsigned int date       = _get_proctime();
1622
1623    unsigned int gpid       = _get_procid();
1624    unsigned int cluster_xy = gpid >> P_WIDTH;
1625    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
1626    unsigned int x          = cluster_xy >> Y_WIDTH;
1627    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
1628
1629    unsigned int task_id    = _get_context_slot(CTX_LTID_ID);
1630
1631    // print exit message
1632    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
1633            "\n       Cause : %s\n\n",
1634            task_id, x, y, lpid, date, string );
1635
1636    // goes to sleeping state
1637    _set_context_slot(CTX_RUN_ID, 0);
1638
1639    // deschedule
1640    _sys_context_switch();
1641
1642    return 0;
1643} 
1644
1645/////////////////////////
1646int _sys_context_switch() 
1647{
1648    unsigned int save_sr;
1649
1650    _it_disable( &save_sr );
1651    _ctx_switch();
1652    _it_restore( &save_sr );
1653
1654    return 0;
1655}
1656
1657////////////////////////
1658int _sys_local_task_id()
1659{
1660    return _get_context_slot(CTX_LTID_ID);
1661}
1662
1663/////////////////////////
1664int _sys_global_task_id()
1665{
1666    return _get_context_slot(CTX_GTID_ID);
1667}
1668
1669////////////////////
1670int _sys_thread_id()
1671{
1672    return _get_context_slot(CTX_TRDID_ID);
1673}
1674
1675////////////////////////////////////////////
1676int _sys_procs_number( unsigned int* x_size,
1677                       unsigned int* y_size,
1678                       unsigned int* nprocs )
1679{
1680    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1681    mapping_cluster_t * cluster = _get_cluster_base(header);
1682
1683    unsigned int x;
1684    unsigned int y;
1685    unsigned int okmin = 1;
1686    unsigned int okmax = 1;
1687
1688    // compute max values
1689    unsigned int xmax  = header->x_size;
1690    unsigned int ymax  = header->y_size;
1691    unsigned int procs = cluster[0].procs;
1692
1693    // check the (ymax-1) lower rows
1694    for ( y = 0 ; y < ymax-1 ; y++ )
1695    {
1696        for ( x = 0 ; x < xmax ; x++ )
1697        {
1698            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
1699        }
1700    }
1701
1702    // check the upper row
1703    for ( x = 0 ; x < xmax ; x++ )
1704    {
1705        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
1706    }
1707
1708    // return values
1709    if ( okmin && okmax )
1710    {
1711        *x_size = xmax;
1712        *y_size = ymax;
1713        *nprocs = procs;
1714    }
1715    else if ( okmin )
1716    {
1717        *x_size = xmax;
1718        *y_size = ymax-1;
1719        *nprocs = procs;
1720    }
1721    else
1722    {
1723        *x_size = 0;
1724        *y_size = 0;
1725        *nprocs = 0;
1726    }
1727    return 0;
1728}
1729
1730///////////////////////////////////////////////////////
1731int _sys_vseg_get_vbase( char*             vspace_name, 
1732                         char*             vseg_name, 
1733                         unsigned int*     vbase ) 
1734{
1735    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1736    mapping_vspace_t * vspace = _get_vspace_base(header);
1737    mapping_vseg_t * vseg     = _get_vseg_base(header);
1738
1739    unsigned int vspace_id;
1740    unsigned int vseg_id;
1741
1742    // scan vspaces
1743    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1744    {
1745        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1746        {
1747            // scan vsegs
1748            for (vseg_id = vspace[vspace_id].vseg_offset; 
1749                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
1750                 vseg_id++) 
1751            {
1752                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
1753                {
1754                    *vbase = vseg[vseg_id].vbase;
1755                    return 0;
1756                }
1757            } 
1758        }
1759    } 
1760    return -1;    // not found
1761}
1762
1763/////////////////////////////////////////////////////////
1764int _sys_vseg_get_length( char*         vspace_name, 
1765                          char*         vseg_name,
1766                          unsigned int* length ) 
1767{
1768    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1769    mapping_vspace_t * vspace = _get_vspace_base(header);
1770    mapping_vseg_t * vseg     = _get_vseg_base(header);
1771
1772    unsigned int vspace_id;
1773    unsigned int vseg_id;
1774
1775    // scan vspaces
1776    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1777    {
1778        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1779        {
1780            // scan vsegs
1781            for (vseg_id = vspace[vspace_id].vseg_offset; 
1782                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
1783                 vseg_id++) 
1784            {
1785                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
1786                {
1787                    *length = vseg[vseg_id].length;
1788                    return 0;
1789                }
1790            } 
1791        }
1792    } 
1793    return -1;    // not found
1794}
1795
1796////////////////////////////////////////
1797int _sys_xy_from_ptr( void*         ptr,
1798                      unsigned int* x,
1799                      unsigned int* y )
1800{
1801    unsigned int flags;
1802    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
1803   
1804    *x = (paddr>>36) & 0xF;
1805    *y = (paddr>>32) & 0xF;
1806
1807    return 0;
1808}
1809
1810/////////////////////////////////////////
1811int _sys_heap_info( unsigned int* vaddr, 
1812                    unsigned int* length,
1813                    unsigned int  x,
1814                    unsigned int  y ) 
1815{
1816    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1817    mapping_task_t *   task    = _get_task_base(header);
1818    mapping_vseg_t *   vseg    = _get_vseg_base(header);
1819    mapping_vspace_t * vspace  = _get_vspace_base(header);
1820
1821    unsigned int task_id;
1822    unsigned int vspace_id;
1823    unsigned int vseg_id = 0xFFFFFFFF;
1824
1825    // searching the heap vseg
1826    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
1827    {
1828        // get vspace global index
1829        vspace_id = _get_context_slot(CTX_VSID_ID);
1830
1831        // scan all tasks in vspace
1832        unsigned int min = vspace[vspace_id].task_offset ;
1833        unsigned int max = min + vspace[vspace_id].tasks ;
1834        for ( task_id = min ; task_id < max ; task_id++ )
1835        {
1836            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
1837            {
1838                vseg_id = task[task_id].heap_vseg_id;
1839                if ( vseg_id != 0xFFFFFFFF ) break;
1840            }
1841        }
1842    }
1843    else                                // searching in the calling task
1844    {
1845        task_id = _get_context_slot(CTX_GTID_ID);
1846        vseg_id = task[task_id].heap_vseg_id;
1847    }
1848
1849    // analysing the vseg_id
1850    if ( vseg_id != 0xFFFFFFFF ) 
1851    {
1852        *vaddr  = vseg[vseg_id].vbase;
1853        *length = vseg[vseg_id].length;
1854        return 0;
1855    }
1856    else 
1857    {
1858        *vaddr  = 0;
1859        *length = 0;
1860        return -1;
1861    }
1862}  // end _sys_heap_info()
1863
1864
1865// Local Variables:
1866// tab-width: 4
1867// c-basic-offset: 4
1868// c-file-offsets:((innamespace . 0)(inline-open . 0))
1869// indent-tabs-mode: nil
1870// End:
1871// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1872
Note: See TracBrowser for help on using the repository browser.