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

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

Introducing support for the coprocessor related system calls.

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