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

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

1) Introducing support for external IRQs dynamic routing.
2) Simplifying the _v2p_translate() function.
3) Removing the generic IOC driver (integrated in the FAT library).

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