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

Last change on this file since 476 was 467, checked in by alain, 10 years ago

Adding a new step in the kernel_init() procedure:
Processor[0][0][0] initialises the distributed kernel heap
allocators, and the distributed lock protecting TTY0.

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