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

Last change on this file since 621 was 614, checked in by bellefin, 9 years ago

Change the syscalls related to the NIC and the CMA
1) In a CHBUF, every buffer is linked to a variable called “status” which is equal to 1 if the buffer is full or 0 if it is empty. The status occupies 64 bytes to simplify cache coherence
2) The CHBUF descriptor now contains the physical addresses of the buffer and its status. It only occupies 64 bits.

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