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

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

Blap.

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