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

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

Remove the vobj object from the mapping_info,
and remove global segment seg_unckdata.

  • Property svn:executable set to *
File size: 47.4 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 <ioc_driver.h>
12#include <nic_driver.h>
13#include <mmc_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
25#if !defined(SEG_BOOT_MAPPING_BASE)
26# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
27#endif
28
29#if !defined(NB_TTY_CHANNELS)
30# error: You must define NB_TTY_CHANNELS in the hard_config.h file
31#endif
32
33#if (NB_TTY_CHANNELS < 1)
34# error: NB_TTY_CHANNELS cannot be smaller than 1!
35#endif
36
37#if !defined(NB_TIM_CHANNELS)
38# error: You must define NB_TIM_CHANNELS in the hard_config.h file
39#endif
40
41#if !defined(NB_NIC_CHANNELS)
42# error: You must define NB_NIC_CHANNELS in the hard_config.h file
43#endif
44
45#if !defined(NB_CMA_CHANNELS)
46# error: You must define NB_CMA_CHANNELS in the hard_config.h file
47#endif
48
49#if !defined(GIET_NO_HARD_CC)
50# error: You must define GIET_NO_HARD_CC in the giet_config.h file
51#endif
52
53#if !defined ( GIET_NIC_MAC4 )
54# error: You must define GIET_NIC_MAC4 in the giet_config.h file
55#endif
56
57#if !defined ( GIET_NIC_MAC2 )
58# error: You must define GIET_NIC_MAC2 in the giet_config.h file
59#endif
60
61
62////////////////////////////////////////////////////////////////////////////
63//     Channel allocators for peripherals
64//     (TTY[0] is reserved for kernel)
65////////////////////////////////////////////////////////////////////////////
66
67__attribute__((section(".kdata")))
68unsigned int _tty_channel_allocator    = 1;
69
70__attribute__((section(".kdata")))
71unsigned int _tim_channel_allocator    = 0;
72
73__attribute__((section(".kdata")))
74unsigned int _cma_channel_allocator    = 0;
75
76__attribute__((section(".kdata")))
77unsigned int _nic_rx_channel_allocator = 0;
78
79__attribute__((section(".kdata")))
80unsigned int _nic_tx_channel_allocator = 0;
81
82////////////////////////////////////////////////////////////////////////////
83// These global variables is defined in tty0.c and tty_driver.c files.
84////////////////////////////////////////////////////////////////////////////
85
86extern sqt_lock_t _tty0_sqt_lock;
87
88extern unsigned int _tty_rx_full[NB_TTY_CHANNELS];
89
90extern unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
91
92////////////////////////////////////////////////////////////////////////////
93//     NIC_RX and NIC_TX chbuf arrays
94////////////////////////////////////////////////////////////////////////////
95
96__attribute__((section(".kdata")))
97nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
98
99__attribute__((section(".kdata")))
100nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
101
102////////////////////////////////////////////////////////////////////////////
103// FBF related chbuf descriptors array, indexed by the CMA channel index.
104// Physical addresses of these chbuf descriptors required for L2 cache sync.
105////////////////////////////////////////////////////////////////////////////
106
107__attribute__((section(".kdata")))
108fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
109
110__attribute__((section(".kdata")))
111unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
112
113////////////////////////////////////////////////////////////////////////////
114//    Initialize the syscall vector with syscall handlers
115// Note: This array must be synchronised with the define in file stdio.h
116////////////////////////////////////////////////////////////////////////////
117
118__attribute__((section(".kdata")))
119const void * _syscall_vector[64] = 
120{
121    &_sys_proc_xyp,         /* 0x00 */
122    &_get_proctime,         /* 0x01 */
123    &_sys_tty_write,        /* 0x02 */
124    &_sys_tty_read,         /* 0x03 */
125    &_sys_tty_alloc,        /* 0x04 */
126    &_sys_tty_get_lock,     /* 0x05 */
127    &_sys_tty_release_lock, /* 0x06 */
128    &_sys_heap_info,        /* 0x07 */
129    &_sys_local_task_id,    /* 0x08 */
130    &_sys_global_task_id,   /* 0x09 */ 
131    &_sys_fbf_cma_alloc,    /* 0x0A */
132    &_sys_fbf_cma_start,    /* 0x0B */
133    &_sys_fbf_cma_display,  /* 0x0C */
134    &_sys_fbf_cma_stop,     /* 0x0D */
135    &_sys_task_exit,        /* 0x0E */
136    &_sys_procs_number,     /* 0x0F */
137
138    &_sys_fbf_sync_write,   /* 0x10 */
139    &_sys_fbf_sync_read,    /* 0x11 */
140    &_sys_thread_id,        /* 0x12 */
141    &_sys_ukn,              /* 0x13 */
142    &_sys_tim_alloc,        /* 0x14 */
143    &_sys_tim_start,        /* 0x15 */ 
144    &_sys_tim_stop,         /* 0x16 */
145    &_sys_ukn,              /* 0x17 */
146    &_sys_ukn,              /* 0x18 */   
147    &_context_switch,       /* 0x19 */
148    &_sys_vseg_get_vbase,   /* 0x1A */
149    &_sys_vseg_get_length,  /* 0x1B */
150    &_sys_xy_from_ptr,      /* 0x1C */
151    &_sys_ukn,              /* 0x1D */
152    &_sys_ukn,              /* 0x1E */
153    &_sys_ukn,              /* 0x1F */
154
155    &_fat_user_open,        /* 0x20 */
156    &_fat_user_read,        /* 0x21 */
157    &_fat_user_write,       /* 0x22 */
158    &_fat_user_lseek,       /* 0x23 */
159    &_fat_fstat,            /* 0x24 */
160    &_fat_close,            /* 0x25 */
161    &_sys_ukn,              /* 0x26 */
162    &_sys_ukn,              /* 0x27 */
163    &_sys_ukn,              /* 0x28 */
164    &_sys_ukn,              /* 0x29 */
165    &_sys_ukn,              /* 0x2A */
166    &_sys_ukn,              /* 0x2B */
167    &_sys_ukn,              /* 0x2C */
168    &_sys_ukn,              /* 0x2D */
169    &_sys_ukn,              /* 0x2E */
170    &_sys_ukn,              /* 0x2F */
171
172    &_sys_nic_alloc,        /* 0x30 */
173    &_sys_nic_start,        /* 0x31 */
174    &_sys_nic_move,         /* 0x32 */
175    &_sys_nic_stop,         /* 0x33 */
176    &_sys_nic_stats,        /* 0x34 */
177    &_sys_nic_clear,        /* 0x35 */ 
178    &_sys_ukn,              /* 0x36 */
179    &_sys_ukn,              /* 0x37 */
180    &_sys_ukn,              /* 0x38 */   
181    &_sys_ukn,              /* 0x39 */
182    &_sys_ukn,              /* 0x3A */
183    &_sys_ukn,              /* 0x3B */
184    &_sys_ukn,              /* 0x3C */
185    &_sys_ukn,              /* 0x3D */
186    &_sys_ukn,              /* 0x3E */
187    &_sys_ukn,              /* 0x3F */
188};
189
190
191//////////////////////////////////////////////////////////////////////////////
192//             TTY related syscall handlers
193//////////////////////////////////////////////////////////////////////////////
194
195////////////////////
196int _sys_tty_alloc()
197{
198    // get a new TTY terminal index
199    unsigned int channel = _atomic_increment( &_tty_channel_allocator, 1 );
200
201    if ( channel >= NB_TTY_CHANNELS )
202    {
203        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n");
204        return -1;
205    }
206    else
207    {
208        _set_context_slot( CTX_TTY_ID, channel );
209        return 0;
210    }
211}
212
213/////////////////////////////////////////////////
214int _sys_tty_write( const char*  buffer,   
215                    unsigned int length,    // number of characters
216                    unsigned int channel)   // channel index
217{
218    unsigned int  nwritten;
219
220    // compute and check tty channel
221    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
222    if( channel >= NB_TTY_CHANNELS ) return -1;
223
224    // write string to TTY channel
225    for (nwritten = 0; nwritten < length; nwritten++) 
226    {
227        // check tty's status
228        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
229
230        // write one byte
231        if (buffer[nwritten] == '\n') 
232        {
233            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
234        }
235        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
236    }
237   
238    return nwritten;
239}
240
241////////////////////////////////////////////////
242int _sys_tty_read( char*        buffer, 
243                   unsigned int length,    // unused
244                   unsigned int channel)   // channel index
245{
246    // compute and check tty channel
247    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
248    if( channel >= NB_TTY_CHANNELS ) return -1;
249
250    // read one character from TTY channel
251    if (_tty_rx_full[channel] == 0) 
252    {
253        return 0;
254    }
255    else 
256    {
257        *buffer = _tty_rx_buf[channel];
258        _tty_rx_full[channel] = 0;
259        return 1;
260    }
261}
262
263///////////////////////////////////////////
264int _sys_tty_get_lock( unsigned int   channel,       // unused
265                       unsigned int * save_sr_ptr )
266{
267    // check tty channel
268    if( channel != 0 )  return 1;
269
270    _it_disable( save_sr_ptr );
271    _sqt_lock_acquire( &_tty0_sqt_lock );
272    return 0;
273}
274
275///////////////////////////////////////////////
276int _sys_tty_release_lock( unsigned int   channel,
277                           unsigned int * save_sr_ptr )
278{
279    // check tty channel
280    if( channel != 0 )  return 1;
281
282    _sqt_lock_release( &_tty0_sqt_lock );
283    _it_restore( save_sr_ptr );
284    return 0;
285}
286
287//////////////////////////////////////////////////////////////////////////////
288//             TIM related syscall handlers
289//////////////////////////////////////////////////////////////////////////////
290
291////////////////////
292int _sys_tim_alloc()
293{
294    // get a new timer index
295    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
296
297    if ( channel >= NB_TIM_CHANNELS )
298    {
299        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
300        return -1;
301    }
302    else
303    {
304        _set_context_slot( CTX_TIM_ID, channel );
305        return 0;
306    }
307}
308
309/////////////////////////////////////////
310int _sys_tim_start( unsigned int period )
311{
312    // get timer index
313    unsigned int channel = _get_context_slot( CTX_TIM_ID );
314    if ( channel >= NB_TIM_CHANNELS )
315    {
316        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
317        return -1;
318    }
319
320    // start timer
321    _timer_start( channel, period );
322
323    return 0;
324}
325
326///////////////////
327int _sys_tim_stop()
328{
329    // get timer index
330    unsigned int channel = _get_context_slot( CTX_TIM_ID );
331    if ( channel >= NB_TIM_CHANNELS )
332    {
333        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
334        return -1;
335    }
336
337    // stop timer
338    _timer_stop( channel );
339
340    return 0;
341}
342
343//////////////////////////////////////////////////////////////////////////////
344//             NIC related syscall handlers
345//////////////////////////////////////////////////////////////////////////////
346
347#define NIC_CONTAINER_SIZE 4096
348
349////////////////////////////////////////
350int _sys_nic_alloc( unsigned int is_rx,
351                    unsigned int xmax,
352                    unsigned int ymax )
353{
354    // check xmax / ymax parameters
355    if ( xmax > X_SIZE )
356    {
357        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
358        return -1;
359    }
360    if ( ymax > Y_SIZE )
361    {
362        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
363        return -1;
364    }
365
366    // get a NIC_RX or NIC_TX channel index
367    unsigned int nic_channel;
368    unsigned int cma_channel;
369
370    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
371    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
372
373    if ( (nic_channel >= NB_NIC_CHANNELS) )
374    {
375        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
376        return -1;
377    }
378
379    // get a CMA channel index
380    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
381
382    if ( cma_channel >= NB_CMA_CHANNELS )
383    {
384        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
385        return -1;
386    }
387
388#if GIET_DEBUG_NIC
389unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
390_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
391        " nic_channel = %d / cma_channel = %d\n"
392        thread , _get_proctime() , nic_channel , cma_channel );
393#endif
394
395    // register nic_index and cma_index in task context
396    if ( is_rx )
397    {
398        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
399        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
400    }
401    else
402    {
403        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
404        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
405    }
406
407    // physical addresses to be registered in the CMA registers
408    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
409    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
410
411    // These variables are used for the various V2P translation
412    unsigned int       ptab  = _get_context_slot(CTX_PTAB_ID);
413    unsigned int       ppn;
414    unsigned int       flags;
415    unsigned int       vaddr;
416
417    // allocate one kernel container per cluster in the (xmax / ymax) mesh
418    unsigned int        cx;              // cluster X coordinate
419    unsigned int        cy;              // cluster Y coordinate
420    unsigned int        index;           // container index in chbuf
421    unsigned long long  cont_paddr;      // container physical address
422
423    for ( cx = 0 ; cx < xmax ; cx++ )
424    {
425        for ( cy = 0 ; cy < ymax ; cy++ )
426        {
427            // compute index in chbuf
428            index = (cx * ymax) + cy; 
429
430            // allocate the kernel container
431            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
432
433            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
434            {
435                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
436                        " in cluster[%d,%d]\n", cx, cy );
437                return -1;
438            }
439
440            // compute container physical address
441            _v2p_translate( (page_table_t*)ptab,
442                            vaddr>>12,
443                            &ppn,
444                            &flags );
445            cont_paddr = (((unsigned long long)ppn) << 12) | (vaddr & 0x00000FFF);
446
447            // initialize chbuf entry
448            if ( is_rx ) _nic_rx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
449            else         _nic_tx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
450
451#if GIET_DEBUG_NIC
452_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start()"
453        " allocates container in cluster[%d,%d] : vaddr = %x / paddr = %l\n",
454        thread , cx , cy , vaddr , cont_paddr );
455#endif
456        }
457    }
458
459    // complete kernel chbuf initialisation
460    if ( is_rx )
461    {
462        _nic_rx_chbuf[nic_channel].xmax = xmax;
463        _nic_rx_chbuf[nic_channel].ymax = ymax;
464    }
465    else
466    {
467        _nic_tx_chbuf[nic_channel].xmax = xmax;
468        _nic_tx_chbuf[nic_channel].ymax = ymax;
469    }
470
471    // compute the NIC chbuf descriptor physical address
472    unsigned int offset;
473    if ( is_rx ) offset = 0x4000;
474    else         offset = 0x4080;
475    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
476                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
477
478#if GIET_DEBUG_NIC
479_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start()"
480        " get NIC chbuf : paddr = %l\n",
481        thread , nic_chbuf_pbase );
482#endif
483
484    // compute the kernel chbuf descriptor physical address
485    if ( is_rx ) vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
486    else         vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
487    _v2p_translate( (page_table_t*)ptab,
488                     vaddr>>12,
489                     &ppn,
490                     &flags );
491    ker_chbuf_pbase = (((unsigned long long)ppn) << 12) | (vaddr & 0x00000FFF);
492
493#if GIET_DEBUG_NIC
494_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start()"
495        " get kernel chbuf : vaddr = %x / paddr = %l\n",
496        thread , vaddr , ker_chbuf_pbase );
497#endif
498
499    // sync the kernel chbuf in L2 after write in L2
500    _mmc_sync( ker_chbuf_pbase, sizeof( nic_chbuf_t ) );
501
502    // initializes CMA registers defining the source & destination chbufs
503    if ( is_rx )               // NIC to kernel
504    {
505        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
506        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
507        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
508        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
509        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
510        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
511    }
512    else                      // kernel to NIC
513    {
514        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
515        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
516        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
517        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
518        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
519        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
520    }
521
522#if GIET_DEBUG_NIC
523_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
524        thread, _get_proctime() );
525#endif
526
527    return nic_channel;
528} // end _sys_nic_alloc()
529
530
531////////////////////////////////////////
532int _sys_nic_start( unsigned int is_rx,
533                    unsigned int channel )
534{
535    unsigned int nic_channel;
536    unsigned int cma_channel;
537
538    // get NIC channel index and CMA channel index from task context
539    if ( is_rx )
540    {
541        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
542        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
543    }
544    else
545    {
546        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
547        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
548    }
549
550#if GIET_DEBUG_NIC
551unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
552_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d"
553        " get NIC channel = %d / CMA channel = %d\n",
554        thread, _get_proctime(), nic_channel, cma_channel );
555#endif
556
557    // check NIC and CMA channels index
558    if ( nic_channel != channel )
559    {
560        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
561        return -1;
562    }
563    if ( cma_channel >= NB_CMA_CHANNELS )
564    {
565        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
566        return -1;
567    }
568
569    // start CMA transfer
570    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
571    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
572    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
573
574    // activates NIC channel
575    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 ); 
576
577#if GIET_DEBUG_NIC
578_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
579        thread , _get_proctime() );
580#endif
581
582    return 0;
583}  // end _sys_nic_start()
584
585
586//////////////////////////////////////
587int _sys_nic_move( unsigned int is_rx,
588                   unsigned int channel,
589                   void*        buffer )
590{
591
592#if GIET_DEBUG_NIC
593unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
594_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
595        thread , _get_proctime() );
596#endif
597
598    // check NIC channel index
599    if ( channel >= NB_NIC_CHANNELS )
600    {
601        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
602        return -1;
603    }
604
605    // get kernel chbuf virtual address
606    nic_chbuf_t* chbuf;
607    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
608    else          chbuf = &_nic_tx_chbuf[channel];
609
610    // get xmax / ymax parameters
611    unsigned int xmax = chbuf->xmax;
612    unsigned int ymax = chbuf->ymax;
613
614    // get cluster coordinates for the processor running the calling task
615    unsigned int  procid = _get_procid();
616    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
617    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
618   
619    // check processor coordinates / (xmax,ymax)
620    if ( cx >= xmax )
621    {
622        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
623                " / xmax = %d\n", cx , xmax );
624        return -1;
625    }
626    if ( cy >= ymax )
627    {
628        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
629                " / ymax = %d\n", cy , ymax );
630        return -1;
631    }
632   
633    unsigned long long user_buffer_paddr;    // user buffer physical address
634    unsigned long long kernel_buffer_paddr;  // kernel buffer physical address
635    unsigned long long kernel_chbuf_paddr;   // kernel chbuf physical address
636    unsigned long long buffer_desc;          // kernel buffer descriptor
637    unsigned long long buffer_desc_paddr;    // kernel buffer descriptor physical address
638    unsigned int       index;                // kernel buffer index in chbuf
639
640    // The following variables are used for V2P translation
641    unsigned int ptab = _get_context_slot( CTX_PTAB_ID );
642    unsigned int ppn;
643    unsigned int flags;
644    unsigned int vaddr;
645
646    // Compute user buffer physical address and check access rights
647    vaddr = (unsigned int)buffer;
648    _v2p_translate( (page_table_t*)ptab,
649                     vaddr>>12,
650                     &ppn,
651                     &flags );
652
653    if ( (flags & PTE_U) == 0 )
654    {
655        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
656        return -1;
657    }
658    user_buffer_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
659
660#if GIET_DEBUG_NIC
661_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
662        thread, user_buffer_paddr );
663#endif
664
665    // compute kernel chbuf physical address (required for sync)
666    vaddr = (unsigned int)chbuf;
667    _v2p_translate( (page_table_t*)ptab,
668                     vaddr>>12,
669                     &ppn,
670                     &flags );
671    kernel_chbuf_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
672
673    // poll local kernel container status until success
674    while ( 1 )
675    {
676        // compute buffer index and buffer descriptor paddr
677        index = (ymax * cx) + cy;
678        buffer_desc_paddr = kernel_chbuf_paddr + (index<<6);
679
680        // inval buffer descriptor in L2 before read in L2
681        _mmc_inval( buffer_desc_paddr , 8 );
682        buffer_desc = chbuf->buffer[index].desc;
683
684#if GIET_DEBUG_NIC
685_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read buffer descriptor %d\n"
686        " at cycle = %d / paddr = %l / buffer descriptor = %l\n",
687        thread, index, _get_proctime(), buffer_desc_paddr, buffer_desc );
688#endif
689
690        // test buffer status and break if found
691        if ( ( is_rx != 0 ) && (buffer_desc >> 63) == 1 )  break;
692        if ( ( is_rx == 0 ) && (buffer_desc >> 63) == 0 )  break;
693    }
694
695    // compute kernel buffer physical address
696    kernel_buffer_paddr = buffer_desc & 0x0000FFFFFFFFFFFFULL;
697   
698    // move one container
699    if ( is_rx )              // RX transfer
700    {
701        // inval kernel buffer in L2 before read in L2
702        _mmc_inval( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
703
704        // transfer data from kernel buffer to user buffer
705        _physical_memcpy( user_buffer_paddr, 
706                          kernel_buffer_paddr, 
707                          NIC_CONTAINER_SIZE );
708#if GIET_DEBUG_NIC
709_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
710        "kernel buffer %l to user buffer %l at cycle %d\n",
711        thread , kernel_buffer_paddr , user_buffer_paddr , _get_proctime() );
712#endif
713
714    }
715    else                      // TX transfer
716    {
717        // transfer data from user buffer to kernel buffer
718        _physical_memcpy( kernel_buffer_paddr, 
719                          user_buffer_paddr, 
720                          NIC_CONTAINER_SIZE );
721
722        // sync kernel buffer in L2 after write in L2
723        _mmc_sync( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
724
725#if GIET_DEBUG_NIC
726_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
727        "user buffer %l to kernel buffer %l at cycle %d\n",
728        thread , user_buffer_paddr , kernel_buffer_paddr , _get_proctime() );
729#endif
730
731    }
732
733    // update kernel chbuf status
734    if ( is_rx ) chbuf->buffer[index].desc = kernel_buffer_paddr & 0x0000FFFFFFFFFFFFULL;
735    else         chbuf->buffer[index].desc = kernel_buffer_paddr | 0x8000000000000000ULL;
736
737    // sync kernel chbuf in L2 after write in L2
738    _mmc_sync( kernel_chbuf_paddr + (index<<6) , 8 );
739
740#if GIET_DEBUG_NIC
741_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
742        thread , index , _get_proctime() );
743#endif
744
745    return 0;
746} // end _sys_nic_move()
747
748
749////////////////////////////////////////
750int _sys_nic_stop( unsigned int is_rx,
751                   unsigned int channel )
752{
753    unsigned int nic_channel;
754    unsigned int cma_channel;
755
756    // get NIC channel index and CMA channel index
757    if ( is_rx )
758    {
759        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
760        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
761    }
762    else
763    {
764        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
765        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
766    }
767
768    // check NIC and CMA channels index
769    if ( nic_channel != channel )
770    {
771        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
772        return -1;
773    }
774    if ( cma_channel >= NB_CMA_CHANNELS )
775    {
776        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
777        return -1;
778    }
779
780    // desactivates the NIC channel
781    _nic_channel_stop( nic_channel, is_rx );
782
783    // desactivates the CMA channel
784    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
785
786    return 0;
787}  // end _sys_nic_stop()
788
789////////////////////////////////////////
790int _sys_nic_clear( unsigned int is_rx,
791                    unsigned int channel )
792{
793    unsigned int nic_channel;
794
795    // get NIC channel
796    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
797    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
798
799    if ( nic_channel != channel )
800    {
801        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
802        return -1;
803    }
804
805    if ( is_rx )
806    {
807        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
808        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
809        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
810        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
811        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
812        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
813        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
814        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
815        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
816    } 
817    else
818    {
819        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
820        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
821        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
822        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
823        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
824        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
825        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
826    }
827    return 0;
828}  // en _sys_nic_clear()
829
830////////////////////////////////////////
831int _sys_nic_stats( unsigned int is_rx,
832                    unsigned int channel )
833{
834    unsigned int nic_channel;
835
836    // get NIC channel
837    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
838    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
839
840    if ( nic_channel != channel )
841    {
842        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
843        return -1;
844    }
845
846    if ( is_rx )
847    {
848        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
849        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
850        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
851        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
852        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
853        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
854        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
855        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
856
857        _printf("\n### Network Controller RX Statistics ###\n"
858                "- packets received : %d\n"
859                "- too small        : %d\n"
860                "- too big          : %d\n"
861                "- fifo full        : %d\n" 
862                "- crc fail         : %d\n" 
863                "- dst mac fail     : %d\n" 
864                "- channel full     : %d\n" 
865                "- broadcast        : %d\n",
866                received,
867                too_small,
868                too_big,
869                fifo_full,
870                crc_fail,
871                dst_fail,
872                ch_full,
873                broadcast );
874    } 
875    else
876    {
877        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
878        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
879        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
880        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
881        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
882        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
883
884        _printf("\n### Network Controller TX Statistics ###\n"
885                "- packets received : %d\n"
886                "- too small        : %d\n"
887                "- too big          : %d\n"
888                "- src mac fail     : %d\n" 
889                "- bypass           : %d\n" 
890                "- broadcast        : %d\n",
891                received,
892                too_big,
893                too_small,
894                src_fail,
895                bypass,
896                broadcast );
897    }
898    return 0;
899}  // end _sys_nic_stats()
900
901/////////////////////////////////////////////////////////////////////////////////////////
902//    FBF related syscall handlers
903/////////////////////////////////////////////////////////////////////////////////////////
904
905/////////////////////////////////////////////
906int _sys_fbf_sync_write( unsigned int offset,
907                         void*        buffer,
908                         unsigned int length )
909{
910    char* fbf_address = (char *)SEG_FBF_BASE + offset;
911    memcpy( fbf_address, buffer, length);
912
913    return 0;
914}
915
916/////////////////////////////////////////////
917int _sys_fbf_sync_read(  unsigned int offset,
918                         void*        buffer,
919                         unsigned int length )
920{
921    char* fbf_address = (char *)SEG_FBF_BASE + offset;
922    memcpy( buffer, fbf_address, length);
923
924    return 0;
925}
926
927////////////////////////
928int _sys_fbf_cma_alloc()
929{
930   // get a new CMA channel index
931    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
932
933    if ( channel >= NB_CMA_CHANNELS )
934    {
935        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
936        return -1;
937    }
938    else
939    {
940        _set_context_slot( CTX_CMA_FB_ID, channel );
941        return 0;
942    }
943} // end sys_fbf_cma_alloc()
944
945////////////////////////////////////////////
946int _sys_fbf_cma_start( void*        vbase0, 
947                        void*        vbase1, 
948                        unsigned int length ) 
949{
950#if NB_CMA_CHANNELS > 0
951
952    unsigned int       ptab;            // page table virtual address
953    unsigned int       vaddr;           // virtual address
954    unsigned int       flags;           // protection flags
955    unsigned int       ppn;             // physical page number
956
957    // get channel index
958    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
959
960    if ( channel >= NB_CMA_CHANNELS )
961    {
962        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
963        return -1;
964    }
965
966#if GIET_DEBUG_FBF_CMA
967_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_start()\n"
968        " - channel      = %d\n"
969        " - buf0   vbase = %x\n"
970        " - buf1   vbase = %x\n"
971        " - buffer size  = %x\n",
972        channel,
973        (unsigned int)vbase0,
974        (unsigned int)vbase1,
975        length );
976#endif
977
978    // checking user buffers virtual addresses and length alignment
979    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 
980    {
981        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer not word aligned\n");
982        return -1;
983    }
984
985    // get page table virtual address
986    ptab = _get_context_slot(CTX_PTAB_ID);
987
988    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
989    vaddr = ((unsigned int)SEG_FBF_BASE);
990    _v2p_translate( (page_table_t*) ptab, 
991                    (vaddr >> 12),
992                    &ppn, 
993                    &flags );
994
995    _fbf_chbuf[channel].fbf.desc = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
996
997    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
998    vaddr = (unsigned int)vbase0; 
999    _v2p_translate( (page_table_t*) ptab, 
1000                    (vaddr >> 12),
1001                    &ppn, 
1002                    &flags );
1003    if ((flags & PTE_U) == 0) 
1004    {
1005        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 0 not in user space\n");
1006        return -1;
1007    }
1008
1009    _fbf_chbuf[channel].buf0.desc = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
1010
1011    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
1012    vaddr = (unsigned int)vbase1; 
1013    _v2p_translate( (page_table_t*) ptab, 
1014                    (vaddr >> 12),
1015                    &ppn, 
1016                    &flags );
1017    if ((flags & PTE_U) == 0) 
1018    {
1019        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 1 not in user space\n");
1020        return -1;
1021    }
1022
1023    _fbf_chbuf[channel].buf1.desc = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
1024
1025    // initializes buffer length
1026    _fbf_chbuf[channel].length = length;
1027
1028    // Compute and register physical adress of the fbf_chbuf descriptor
1029    vaddr = (unsigned int)(&_fbf_chbuf[channel]);
1030    _v2p_translate( (page_table_t*) ptab, 
1031                    (vaddr >> 12),
1032                    &ppn, 
1033                    &flags );
1034 
1035    _fbf_chbuf_paddr[channel] = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
1036
1037    if ( USE_IOB )
1038    {
1039        // SYNC request for fbf_chbuf descriptor
1040        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
1041    }
1042
1043#if GIET_DEBUG_FBF_CMA
1044_printf(" - fbf    pbase = %l\n"
1045        " - buf0   pbase = %l\n"
1046        " - buf1   pbase = %l\n"
1047        " - chbuf  pbase = %l\n",
1048        _fbf_chbuf[channel].fbf.desc,
1049        _fbf_chbuf[channel].buf0.desc,
1050        _fbf_chbuf[channel].buf1.desc,
1051        _fbf_chbuf_paddr[channel] );
1052#endif
1053
1054    // start CMA transfer
1055    unsigned long long paddr = _fbf_chbuf_paddr[channel];
1056    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
1057    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
1058    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 128;
1059    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
1060
1061    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
1062    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
1063    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
1064    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
1065    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
1066    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
1067    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
1068    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
1069    _cma_set_register( channel, CHBUF_RUN      , 1 );
1070
1071    return 0;
1072
1073#else
1074
1075    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1076    return -1;
1077
1078#endif
1079} // end _sys_fbf_cma_start()
1080
1081/////////////////////////////////////////////////////
1082int _sys_fbf_cma_display( unsigned int buffer_index )
1083{
1084#if NB_CMA_CHANNELS > 0
1085
1086    volatile unsigned int full = 1;
1087
1088    // get channel index
1089    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1090
1091    if ( channel >= NB_CMA_CHANNELS )
1092    {
1093        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1094                "CMA channel index too large\n");
1095        return -1;
1096    }
1097
1098    // get fbf_chbuf descriptor pointer
1099    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1100
1101#if GIET_DEBUG_FBF_CMA
1102_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
1103        " - cma channel     = %d\n"
1104        " - buffer index    = %d\n"
1105        " - buf0_desc value = %l\n"
1106        " - buf1_desc value = %l\n"
1107        " - fbf_desc  value = %l\n",
1108        channel , buffer_index,
1109        _fbf_chbuf[channel].buf0.desc,
1110        _fbf_chbuf[channel].buf1.desc,
1111        _fbf_chbuf[channel].fbf.desc );
1112#endif
1113
1114    if ( buffer_index == 0 )    // user buffer 0
1115    {
1116        // INVAL L1 and L2 cache copies of user buffer descriptor,
1117        // because it has been modified in RAM by the CMA component
1118        _dcache_buf_invalidate( (unsigned int)pdesc , sizeof(buffer_descriptor_t) );
1119        _mmc_inval( _fbf_chbuf_paddr[channel] , sizeof(buffer_descriptor_t) );
1120
1121        // waiting user buffer released by the CMA component)
1122        while ( full )
1123        { 
1124            full = (unsigned int)(pdesc->buf0.desc >> 63);
1125        }
1126
1127        // SYNC request for the user buffer, because
1128        // it will be read from XRAM by the CMA component
1129        _mmc_sync( pdesc->buf0.desc , pdesc->length );
1130
1131        // set user buffer status
1132        pdesc->buf0.desc = pdesc->buf0.desc | 0x8000000000000000ULL;
1133
1134        // reset fbf buffer status
1135        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
1136
1137        // SYNC request, because these buffer descriptors
1138        // will be read from XRAM by the CMA component
1139        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
1140    }
1141    else                        // user buffer 1
1142    {
1143        // INVAL L1 and L2 cache copies of user buffer descriptor,
1144        // because it has been modified in RAM by the CMA component
1145        _dcache_buf_invalidate( (unsigned int)pdesc + 64, sizeof(buffer_descriptor_t) );
1146        _mmc_inval( _fbf_chbuf_paddr[channel] + 64, sizeof(buffer_descriptor_t) );
1147
1148        // waiting user buffer released by the CMA component)
1149        while ( full )
1150        { 
1151            full = (unsigned int)(pdesc->buf1.desc >> 63);
1152        }
1153
1154        // SYNC request for the user buffer, because
1155        // it will be read from XRAM by the CMA component
1156        _mmc_sync( pdesc->buf1.desc , pdesc->length );
1157
1158        // set user buffer status
1159        pdesc->buf1.desc = pdesc->buf1.desc | 0x8000000000000000ULL;
1160
1161        // reset fbf buffer status
1162        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
1163
1164        // SYNC request, because these buffer descriptors
1165        // will be read from XRAM by the CMA component
1166        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
1167    }
1168
1169#if GIET_DEBUG_FBF_CMA
1170_printf("\n[FBF_CMA DEBUG] exit _sys_fb_cma_display()\n"
1171        " - buf0_desc value = %l\n"
1172        " - buf1_desc value = %l\n"
1173        " - fbf_desc  value = %l\n",
1174        _fbf_chbuf[channel].buf0.desc,
1175        _fbf_chbuf[channel].buf1.desc,
1176        _fbf_chbuf[channel].fbf.desc );
1177#endif
1178
1179    return 0;
1180
1181#else
1182
1183    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1184    return -1;
1185
1186#endif
1187} // end _sys_fbf_cma_display()
1188
1189
1190///////////////////////
1191int _sys_fbf_cma_stop()
1192{
1193#if NB_CMA_CHANNELS > 0
1194
1195    // get channel index
1196    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1197
1198    if ( channel >= NB_CMA_CHANNELS )
1199    {
1200        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
1201        return -1;
1202    }
1203
1204    // Desactivate CMA channel
1205    _cma_set_register( channel, CHBUF_RUN, 0 );
1206
1207    return 0;
1208
1209#else
1210
1211    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
1212    return -1;
1213
1214#endif
1215} // end _sys_fbf_cma_stop()
1216
1217
1218//////////////////////////////////////////////////////////////////////////////
1219//           Miscelaneous syscall handlers
1220//////////////////////////////////////////////////////////////////////////////
1221
1222///////////////
1223int _sys_ukn() 
1224{
1225    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
1226    return -1;
1227}
1228
1229////////////////////////////////////
1230int _sys_proc_xyp( unsigned int* x,
1231                   unsigned int* y,
1232                   unsigned int* p )
1233{
1234    unsigned int gpid = _get_procid();  // global processor index from CPO register
1235
1236    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
1237    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1238    *p = gpid & ((1<<P_WIDTH)-1);
1239
1240    return 0;
1241}
1242
1243//////////////////////////////////
1244int _sys_task_exit( char* string ) 
1245{
1246    unsigned int date       = _get_proctime();
1247
1248    unsigned int gpid       = _get_procid();
1249    unsigned int cluster_xy = gpid >> P_WIDTH;
1250    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
1251    unsigned int x          = cluster_xy >> Y_WIDTH;
1252    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
1253
1254    unsigned int task_id    = _get_context_slot(CTX_LTID_ID);
1255
1256    // print exit message
1257    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
1258            "\n       Cause : %s\n\n",
1259            task_id, x, y, lpid, date, string );
1260
1261    // goes to sleeping state
1262    _set_context_slot(CTX_RUN_ID, 0);
1263
1264    // deschedule
1265    _context_switch();
1266
1267    return 0;
1268} 
1269
1270//////////////////////
1271int _context_switch() 
1272{
1273    unsigned int save_sr;
1274
1275    _it_disable( &save_sr );
1276    _ctx_switch();
1277    _it_restore( &save_sr );
1278
1279    return 0;
1280}
1281
1282////////////////////////
1283int _sys_local_task_id()
1284{
1285    return _get_context_slot(CTX_LTID_ID);
1286}
1287
1288/////////////////////////
1289int _sys_global_task_id()
1290{
1291    return _get_context_slot(CTX_GTID_ID);
1292}
1293
1294////////////////////
1295int _sys_thread_id()
1296{
1297    return _get_context_slot(CTX_TRDID_ID);
1298}
1299
1300////////////////////////////////////////////
1301int _sys_procs_number( unsigned int* x_size,
1302                       unsigned int* y_size,
1303                       unsigned int* nprocs )
1304{
1305    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1306    mapping_cluster_t * cluster = _get_cluster_base(header);
1307
1308    unsigned int x;
1309    unsigned int y;
1310    unsigned int okmin = 1;
1311    unsigned int okmax = 1;
1312
1313    // compute max values
1314    unsigned int xmax  = header->x_size;
1315    unsigned int ymax  = header->y_size;
1316    unsigned int procs = cluster[0].procs;
1317
1318    // check the (ymax-1) lower rows
1319    for ( y = 0 ; y < ymax-1 ; y++ )
1320    {
1321        for ( x = 0 ; x < xmax ; x++ )
1322        {
1323            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
1324        }
1325    }
1326
1327    // check the upper row
1328    for ( x = 0 ; x < xmax ; x++ )
1329    {
1330        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
1331    }
1332
1333    // return values
1334    if ( okmin && okmax )
1335    {
1336        *x_size = xmax;
1337        *y_size = ymax;
1338        *nprocs = procs;
1339    }
1340    else if ( okmin )
1341    {
1342        *x_size = xmax;
1343        *y_size = ymax-1;
1344        *nprocs = procs;
1345    }
1346    else
1347    {
1348        *x_size = 0;
1349        *y_size = 0;
1350        *nprocs = 0;
1351    }
1352    return 0;
1353}
1354
1355///////////////////////////////////////////////////////
1356int _sys_vseg_get_vbase( char*             vspace_name, 
1357                         char*             vseg_name, 
1358                         unsigned int*     vbase ) 
1359{
1360    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1361    mapping_vspace_t * vspace = _get_vspace_base(header);
1362    mapping_vseg_t * vseg     = _get_vseg_base(header);
1363
1364    unsigned int vspace_id;
1365    unsigned int vseg_id;
1366
1367    // scan vspaces
1368    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1369    {
1370        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1371        {
1372            // scan vsegs
1373            for (vseg_id = vspace[vspace_id].vseg_offset; 
1374                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
1375                 vseg_id++) 
1376            {
1377                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
1378                {
1379                    *vbase = vseg[vseg_id].vbase;
1380                    return 0;
1381                }
1382            } 
1383        }
1384    } 
1385    return -1;    // not found
1386}
1387
1388/////////////////////////////////////////////////////////
1389int _sys_vseg_get_length( char*         vspace_name, 
1390                          char*         vseg_name,
1391                          unsigned int* length ) 
1392{
1393    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1394    mapping_vspace_t * vspace = _get_vspace_base(header);
1395    mapping_vseg_t * vseg     = _get_vseg_base(header);
1396
1397    unsigned int vspace_id;
1398    unsigned int vseg_id;
1399
1400    // scan vspaces
1401    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1402    {
1403        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1404        {
1405            // scan vsegs
1406            for (vseg_id = vspace[vspace_id].vseg_offset; 
1407                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
1408                 vseg_id++) 
1409            {
1410                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
1411                {
1412                    *length = vseg[vseg_id].length;
1413                    return 0;
1414                }
1415            } 
1416        }
1417    } 
1418    return -1;    // not found
1419}
1420
1421////////////////////////////////////////
1422int _sys_xy_from_ptr( void*         ptr,
1423                      unsigned int* x,
1424                      unsigned int* y )
1425{
1426    unsigned int ppn;
1427    unsigned int flags;
1428    unsigned int vpn  = (((unsigned int)ptr)>>12);
1429   
1430    // get the page table pointer
1431    page_table_t* pt = (page_table_t*)_get_context_slot( CTX_PTAB_ID ); 
1432
1433    // compute the physical address
1434    _v2p_translate( pt, vpn, &ppn, &flags );
1435
1436    *x = (ppn>>24) & 0xF;
1437    *y = (ppn>>20) & 0xF;
1438    return 0;
1439}
1440
1441/////////////////////////////////////////
1442int _sys_heap_info( unsigned int* vaddr, 
1443                    unsigned int* length,
1444                    unsigned int  x,
1445                    unsigned int  y ) 
1446{
1447    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1448    mapping_task_t *   task    = _get_task_base(header);
1449    mapping_vseg_t *   vseg    = _get_vseg_base(header);
1450    mapping_vspace_t * vspace  = _get_vspace_base(header);
1451
1452    unsigned int task_id;
1453    unsigned int vspace_id;
1454    unsigned int vseg_id = 0xFFFFFFFF;
1455
1456    // searching the heap vseg
1457    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
1458    {
1459        // get vspace global index
1460        vspace_id = _get_context_slot(CTX_VSID_ID);
1461
1462        // scan all tasks in vspace
1463        unsigned int min = vspace[vspace_id].task_offset ;
1464        unsigned int max = min + vspace[vspace_id].tasks ;
1465        for ( task_id = min ; task_id < max ; task_id++ )
1466        {
1467            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
1468            {
1469                vseg_id = task[task_id].heap_vseg_id;
1470                if ( vseg_id != 0xFFFFFFFF ) break;
1471            }
1472        }
1473    }
1474    else                                // searching in the calling task
1475    {
1476        task_id = _get_context_slot(CTX_GTID_ID);
1477        vseg_id = task[task_id].heap_vseg_id;
1478    }
1479
1480    // analysing the vseg_id
1481    if ( vseg_id != 0xFFFFFFFF ) 
1482    {
1483        *vaddr  = vseg[vseg_id].vbase;
1484        *length = vseg[vseg_id].length;
1485        return 0;
1486    }
1487    else 
1488    {
1489        *vaddr  = 0;
1490        *length = 0;
1491        return -1;
1492    }
1493}  // end _sys_heap_info()
1494
1495
1496// Local Variables:
1497// tab-width: 4
1498// c-basic-offset: 4
1499// c-file-offsets:((innamespace . 0)(inline-open . 0))
1500// indent-tabs-mode: nil
1501// End:
1502// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1503
Note: See TracBrowser for help on using the repository browser.