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

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

Introducing an explicit (channel) argument in all kernel access functions to NIC.

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