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

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

Fixing a bug in _sys_fbf_cma_start() function.

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