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

Last change on this file since 499 was 494, checked in by alain, 10 years ago

Introduce a fully parallel procedure for the kernel initialisation.

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