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

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

Introducing support for hardware coprocessors
using the vci_mwmr_dma components.

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